Merge remote-tracking branch 'refs/remotes/origin/master'
Merge changes made on visual studio repo.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#ifndef YAZE_CORE_COMMON_H
|
#ifndef YAZE_CORE_COMMON_H
|
||||||
#define YAZE_CORE_COMMON_H
|
#define YAZE_CORE_COMMON_H
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -10,6 +11,7 @@
|
|||||||
#include "absl/container/flat_hash_map.h"
|
#include "absl/container/flat_hash_map.h"
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
|
#include "absl/strings/str_cat.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
|
|
||||||
@@ -56,12 +58,6 @@ class ExperimentFlags {
|
|||||||
// Attempt to run the dungeon room draw routine when opening a room.
|
// Attempt to run the dungeon room draw routine when opening a room.
|
||||||
bool kDrawDungeonRoomGraphics = true;
|
bool kDrawDungeonRoomGraphics = true;
|
||||||
|
|
||||||
// Use the new platform specific file dialog wrappers.
|
|
||||||
bool kNewFileDialogWrapper = true;
|
|
||||||
|
|
||||||
// Uses texture streaming from SDL for my dynamic updates.
|
|
||||||
bool kLoadTexturesAsStreaming = true;
|
|
||||||
|
|
||||||
// Save dungeon map edits to the Rom.
|
// Save dungeon map edits to the Rom.
|
||||||
bool kSaveDungeonMaps = false;
|
bool kSaveDungeonMaps = false;
|
||||||
|
|
||||||
@@ -113,10 +109,6 @@ class ExperimentFlags {
|
|||||||
"\n";
|
"\n";
|
||||||
result += "kDrawDungeonRoomGraphics: " +
|
result += "kDrawDungeonRoomGraphics: " +
|
||||||
std::to_string(get().kDrawDungeonRoomGraphics) + "\n";
|
std::to_string(get().kDrawDungeonRoomGraphics) + "\n";
|
||||||
result += "kNewFileDialogWrapper: " +
|
|
||||||
std::to_string(get().kNewFileDialogWrapper) + "\n";
|
|
||||||
result += "kLoadTexturesAsStreaming: " +
|
|
||||||
std::to_string(get().kLoadTexturesAsStreaming) + "\n";
|
|
||||||
result +=
|
result +=
|
||||||
"kSaveDungeonMaps: " + std::to_string(get().kSaveDungeonMaps) + "\n";
|
"kSaveDungeonMaps: " + std::to_string(get().kSaveDungeonMaps) + "\n";
|
||||||
result += "kLogToConsole: " + std::to_string(get().kLogToConsole) + "\n";
|
result += "kLogToConsole: " + std::to_string(get().kLogToConsole) + "\n";
|
||||||
@@ -182,17 +174,23 @@ class NotifyValue {
|
|||||||
T temp_value_;
|
T temp_value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool log_to_console = false;
|
|
||||||
static const std::string kLogFileOut = "yaze_log.txt";
|
static const std::string kLogFileOut = "yaze_log.txt";
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static void logf(const absl::FormatSpec<Args...> &format, const Args &...args) {
|
static void logf(const absl::FormatSpec<Args...> &format, const Args &...args) {
|
||||||
std::string message = absl::StrFormat(format, args...);
|
std::string message = absl::StrFormat(format, args...);
|
||||||
if (log_to_console) {
|
auto timestamp = std::chrono::system_clock::now();
|
||||||
std::cout << message << std::endl;
|
|
||||||
|
std::time_t now_tt = std::chrono::system_clock::to_time_t(timestamp);
|
||||||
|
std::tm tm = *std::localtime(&now_tt);
|
||||||
|
message = absl::StrCat("[", tm.tm_hour, ":", tm.tm_min, ":", tm.tm_sec, "] ",
|
||||||
|
message, "\n");
|
||||||
|
|
||||||
|
if (ExperimentFlags::get().kLogToConsole) {
|
||||||
|
std::cout << message;
|
||||||
}
|
}
|
||||||
static std::ofstream fout(kLogFileOut, std::ios::out | std::ios::app);
|
static std::ofstream fout(kLogFileOut, std::ios::out | std::ios::app);
|
||||||
fout << message << std::endl;
|
fout << message;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr uint32_t kFastRomRegion = 0x808000;
|
constexpr uint32_t kFastRomRegion = 0x808000;
|
||||||
|
|||||||
@@ -154,11 +154,11 @@ absl::Status Controller::CreateWindow() {
|
|||||||
|
|
||||||
window_ = std::unique_ptr<SDL_Window, core::SDL_Deleter>(
|
window_ = std::unique_ptr<SDL_Window, core::SDL_Deleter>(
|
||||||
SDL_CreateWindow("Yet Another Zelda3 Editor", // window title
|
SDL_CreateWindow("Yet Another Zelda3 Editor", // window title
|
||||||
SDL_WINDOWPOS_UNDEFINED, // initial x position
|
SDL_WINDOWPOS_UNDEFINED, // initial x position
|
||||||
SDL_WINDOWPOS_UNDEFINED, // initial y position
|
SDL_WINDOWPOS_UNDEFINED, // initial y position
|
||||||
screen_width, // width, in pixels
|
screen_width, // width, in pixels
|
||||||
screen_height, // height, in pixels
|
screen_height, // height, in pixels
|
||||||
SDL_WINDOW_RESIZABLE),
|
SDL_WINDOW_RESIZABLE),
|
||||||
core::SDL_Deleter());
|
core::SDL_Deleter());
|
||||||
if (window_ == nullptr) {
|
if (window_ == nullptr) {
|
||||||
return absl::InternalError(
|
return absl::InternalError(
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace core {
|
|||||||
* This class is responsible for managing the main window and the
|
* This class is responsible for managing the main window and the
|
||||||
* main editor. It is the main entry point for the application.
|
* main editor. It is the main entry point for the application.
|
||||||
*/
|
*/
|
||||||
class Controller : public ExperimentFlags {
|
class Controller {
|
||||||
public:
|
public:
|
||||||
bool IsActive() const { return active_; }
|
bool IsActive() const { return active_; }
|
||||||
absl::Status OnEntry(std::string filename = "");
|
absl::Status OnEntry(std::string filename = "");
|
||||||
@@ -53,13 +53,13 @@ class Controller : public ExperimentFlags {
|
|||||||
auto window() -> SDL_Window * { return window_.get(); }
|
auto window() -> SDL_Window * { return window_.get(); }
|
||||||
void init_test_editor(editor::Editor *editor) { test_editor_ = editor; }
|
void init_test_editor(editor::Editor *editor) { test_editor_ = editor; }
|
||||||
void set_active(bool active) { active_ = active; }
|
void set_active(bool active) { active_ = active; }
|
||||||
auto active() { return active_; }
|
auto active() const { return active_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend int ::main(int argc, char **argv);
|
friend int ::main(int argc, char **argv);
|
||||||
|
|
||||||
bool active_ = false;
|
bool active_ = false;
|
||||||
Platform platform_;
|
Platform platform_ = Platform::kUnknown;
|
||||||
editor::Editor *test_editor_ = nullptr;
|
editor::Editor *test_editor_ = nullptr;
|
||||||
editor::EditorManager editor_manager_;
|
editor::EditorManager editor_manager_;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "app/core/constants.h"
|
||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
@@ -15,19 +16,88 @@
|
|||||||
namespace yaze {
|
namespace yaze {
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
|
static const char* KARLA_REGULAR = "Karla-Regular.ttf";
|
||||||
|
static const char* ROBOTO_MEDIUM = "Roboto-Medium.ttf";
|
||||||
|
static const char* COUSINE_REGULAR = "Cousine-Regular.ttf";
|
||||||
|
static const char* DROID_SANS = "DroidSans.ttf";
|
||||||
|
static const char* NOTO_SANS_JP = "NotoSansJP.ttf";
|
||||||
|
static const char* IBM_PLEX_JP = "IBMPlexSansJP-Bold.ttf";
|
||||||
|
|
||||||
|
static const float FONT_SIZE_DEFAULT = 16.0f;
|
||||||
|
static const float FONT_SIZE_DROID_SANS = 18.0f;
|
||||||
|
static const float ICON_FONT_SIZE = 18.0f;
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::string SetFontPath(const std::string& font_path) {
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#if TARGET_OS_IOS == 1
|
||||||
|
const std::string kBundlePath = GetBundleResourcePath();
|
||||||
|
return kBundlePath + font_path;
|
||||||
|
#else
|
||||||
|
return absl::StrCat(GetBundleResourcePath(), "Contents/Resources/font/",
|
||||||
|
font_path);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
return absl::StrCat("assets/font/", font_path);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status LoadFont(const FontConfig& font_config) {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
std::string actual_font_path = SetFontPath(font_config.font_path);
|
||||||
|
// Check if the file exists with std library first, since ImGui IO will assert
|
||||||
|
// if the file does not exist
|
||||||
|
if (!std::filesystem::exists(actual_font_path)) {
|
||||||
|
return absl::InternalError(
|
||||||
|
absl::StrFormat("Font file %s does not exist", actual_font_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!io.Fonts->AddFontFromFileTTF(actual_font_path.data(), font_config.font_size)) {
|
||||||
|
return absl::InternalError(
|
||||||
|
absl::StrFormat("Failed to load font from %s", actual_font_path));
|
||||||
|
}
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status AddIconFont() {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
static const ImWchar icons_ranges[] = { ICON_MIN_MD, 0xf900, 0 };
|
||||||
|
ImFontConfig icons_config;
|
||||||
|
icons_config.MergeMode = true;
|
||||||
|
icons_config.GlyphOffset.y = 5.0f;
|
||||||
|
icons_config.GlyphMinAdvanceX = 13.0f;
|
||||||
|
icons_config.PixelSnapH = true;
|
||||||
|
std::string icon_font_path = SetFontPath(FONT_ICON_FILE_NAME_MD);
|
||||||
|
if (!io.Fonts->AddFontFromFileTTF(icon_font_path.c_str(), ICON_FONT_SIZE,
|
||||||
|
&icons_config, icons_ranges)) {
|
||||||
|
return absl::InternalError("Failed to add icon fonts");
|
||||||
|
}
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status AddJapaneseFont() {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImFontConfig japanese_font_config;
|
||||||
|
japanese_font_config.MergeMode = true;
|
||||||
|
japanese_font_config.GlyphOffset.y = 5.0f;
|
||||||
|
japanese_font_config.GlyphMinAdvanceX = 13.0f;
|
||||||
|
japanese_font_config.PixelSnapH = true;
|
||||||
|
std::string japanese_font_path = SetFontPath(NOTO_SANS_JP);
|
||||||
|
if (!io.Fonts->AddFontFromFileTTF(japanese_font_path.data(), ICON_FONT_SIZE,
|
||||||
|
&japanese_font_config,
|
||||||
|
io.Fonts->GetGlyphRangesJapanese())) {
|
||||||
|
return absl::InternalError("Failed to add Japanese fonts");
|
||||||
|
}
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
absl::Status LoadPackageFonts() {
|
absl::Status LoadPackageFonts() {
|
||||||
ImGuiIO &io = ImGui::GetIO();
|
ImGuiIO &io = ImGui::GetIO();
|
||||||
|
|
||||||
static const char *KARLA_REGULAR = "Karla-Regular.ttf";
|
|
||||||
static const char *ROBOTO_MEDIUM = "Roboto-Medium.ttf";
|
|
||||||
static const char *COUSINE_REGULAR = "Cousine-Regular.ttf";
|
|
||||||
static const char *DROID_SANS = "DroidSans.ttf";
|
|
||||||
static const char *NOTO_SANS_JP = "NotoSansJP.ttf";
|
|
||||||
static const char *IBM_PLEX_JP = "IBMPlexSansJP-Bold.ttf";
|
|
||||||
static const float FONT_SIZE_DEFAULT = 16.0f;
|
|
||||||
static const float FONT_SIZE_DROID_SANS = 18.0f;
|
|
||||||
static const float ICON_FONT_SIZE = 18.0f;
|
|
||||||
|
|
||||||
// Icon configuration
|
// Icon configuration
|
||||||
static const ImWchar icons_ranges[] = {ICON_MIN_MD, 0xf900, 0};
|
static const ImWchar icons_ranges[] = {ICON_MIN_MD, 0xf900, 0};
|
||||||
ImFontConfig icons_config;
|
ImFontConfig icons_config;
|
||||||
@@ -52,70 +122,30 @@ absl::Status LoadPackageFonts() {
|
|||||||
float font_size =
|
float font_size =
|
||||||
(font_path == DROID_SANS) ? FONT_SIZE_DROID_SANS : FONT_SIZE_DEFAULT;
|
(font_path == DROID_SANS) ? FONT_SIZE_DROID_SANS : FONT_SIZE_DEFAULT;
|
||||||
|
|
||||||
std::string actual_font_path;
|
FontConfig font_config = { font_path, font_size };
|
||||||
#ifdef __APPLE__
|
RETURN_IF_ERROR(LoadFont(font_config));
|
||||||
#if TARGET_OS_IOS == 1
|
|
||||||
const std::string kBundlePath = GetBundleResourcePath();
|
|
||||||
actual_font_path = kBundlePath + font_path;
|
|
||||||
#else
|
|
||||||
actual_font_path = absl::StrCat(GetBundleResourcePath(),
|
|
||||||
"Contents/Resources/font/", font_path);
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
actual_font_path = absl::StrCat("assets/font/", font_path);
|
|
||||||
actual_font_path = std::filesystem::absolute(actual_font_path).string();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!io.Fonts->AddFontFromFileTTF(actual_font_path.data(), font_size)) {
|
|
||||||
return absl::InternalError(
|
|
||||||
absl::StrFormat("Failed to load font from %s", actual_font_path));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge icon set
|
// Merge icon set
|
||||||
std::string actual_icon_font_path = "";
|
RETURN_IF_ERROR(AddIconFont());
|
||||||
const char *icon_font_path = FONT_ICON_FILE_NAME_MD;
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
|
||||||
#if TARGET_OS_IOS == 1
|
|
||||||
const std::string kIconBundlePath = GetBundleResourcePath();
|
|
||||||
actual_icon_font_path = kIconBundlePath + "MaterialIcons-Regular.ttf";
|
|
||||||
#else
|
|
||||||
actual_icon_font_path =
|
|
||||||
absl::StrCat(GetBundleResourcePath(),
|
|
||||||
"Contents/Resources/font/MaterialIcons-Regular.ttf");
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
actual_icon_font_path = std::filesystem::absolute(icon_font_path).string();
|
|
||||||
#endif
|
|
||||||
if (!io.Fonts->AddFontFromFileTTF(actual_icon_font_path.data(),
|
|
||||||
ICON_FONT_SIZE, &icons_config,
|
|
||||||
icons_ranges)) {
|
|
||||||
return absl::InternalError("Failed to load icon fonts");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge Japanese font
|
// Merge Japanese font
|
||||||
std::string actual_japanese_font_path = "";
|
RETURN_IF_ERROR(AddJapaneseFont());
|
||||||
const char *japanese_font_path = NOTO_SANS_JP;
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
|
||||||
#if TARGET_OS_IOS == 1
|
|
||||||
const std::string kJapaneseBundlePath = GetBundleResourcePath();
|
|
||||||
actual_japanese_font_path = kJapaneseBundlePath + japanese_font_path;
|
|
||||||
#else
|
|
||||||
actual_japanese_font_path =
|
|
||||||
absl::StrCat(GetBundleResourcePath(), "Contents/Resources/font/",
|
|
||||||
japanese_font_path);
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
actual_japanese_font_path = absl::StrCat("assets/font/", japanese_font_path);
|
|
||||||
actual_japanese_font_path =
|
|
||||||
std::filesystem::absolute(actual_japanese_font_path).string();
|
|
||||||
#endif
|
|
||||||
io.Fonts->AddFontFromFileTTF(actual_japanese_font_path.data(), 18.0f,
|
|
||||||
&japanese_font_config,
|
|
||||||
io.Fonts->GetGlyphRangesJapanese());
|
|
||||||
}
|
}
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
absl::Status ReloadPackageFont(const FontConfig& config) {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
std::string actual_font_path = SetFontPath(config.font_path);
|
||||||
|
if (!io.Fonts->AddFontFromFileTTF(actual_font_path.data(), config.font_size)) {
|
||||||
|
return absl::InternalError(
|
||||||
|
absl::StrFormat("Failed to load font from %s", actual_font_path));
|
||||||
|
}
|
||||||
|
RETURN_IF_ERROR(AddIconFont());
|
||||||
|
RETURN_IF_ERROR(AddJapaneseFont());
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
@@ -235,7 +265,6 @@ void LoadSystemFonts() {
|
|||||||
|
|
||||||
void LoadSystemFonts() {
|
void LoadSystemFonts() {
|
||||||
// Load Linux System Fonts into ImGui
|
// Load Linux System Fonts into ImGui
|
||||||
// ...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,9 +6,17 @@
|
|||||||
namespace yaze {
|
namespace yaze {
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
void LoadSystemFonts();
|
struct FontConfig {
|
||||||
|
const char* font_path;
|
||||||
|
float font_size;
|
||||||
|
};
|
||||||
|
|
||||||
absl::Status LoadPackageFonts();
|
absl::Status LoadPackageFonts();
|
||||||
|
|
||||||
|
absl::Status ReloadPackageFont(const FontConfig& config);
|
||||||
|
|
||||||
|
void LoadSystemFonts();
|
||||||
|
|
||||||
} // namespace core
|
} // namespace core
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ absl::Status DungeonEditor::Initialize() {
|
|||||||
ASSIGN_OR_RETURN(current_palette_group_,
|
ASSIGN_OR_RETURN(current_palette_group_,
|
||||||
gfx::CreatePaletteGroupFromLargePalette(full_palette_));
|
gfx::CreatePaletteGroupFromLargePalette(full_palette_));
|
||||||
|
|
||||||
graphics_bin_ = rom()->gfx_sheets();
|
graphics_bin_ = GraphicsSheetManager::GetInstance().gfx_sheets();
|
||||||
// Create a vector of pointers to the current block bitmaps
|
// Create a vector of pointers to the current block bitmaps
|
||||||
for (int block : rooms_[current_room_id_].blocks()) {
|
for (int block : rooms_[current_room_id_].blocks()) {
|
||||||
room_gfx_sheets_.emplace_back(&graphics_bin_[block]);
|
room_gfx_sheets_.emplace_back(&graphics_bin_[block]);
|
||||||
|
|||||||
@@ -58,19 +58,22 @@ void EditorManager::Initialize(std::string filename) {
|
|||||||
absl::Status EditorManager::Update() {
|
absl::Status EditorManager::Update() {
|
||||||
ManageKeyboardShortcuts();
|
ManageKeyboardShortcuts();
|
||||||
|
|
||||||
DrawYazeMenu();
|
DrawMenuBar();
|
||||||
DrawStatusPopup();
|
DrawPopups();
|
||||||
DrawAboutPopup();
|
|
||||||
DrawInfoPopup();
|
|
||||||
|
|
||||||
if (rom()->is_loaded() && !rom_assets_loaded_) {
|
if (rom()->is_loaded() && !rom_assets_loaded_) {
|
||||||
RETURN_IF_ERROR(rom()->LoadAllGraphicsData())
|
auto& sheet_manager = GraphicsSheetManager::GetInstance();
|
||||||
|
ASSIGN_OR_RETURN(*sheet_manager.mutable_gfx_sheets(),
|
||||||
|
LoadAllGraphicsData(*rom()))
|
||||||
RETURN_IF_ERROR(overworld_editor_.LoadGraphics());
|
RETURN_IF_ERROR(overworld_editor_.LoadGraphics());
|
||||||
rom_assets_loaded_ = true;
|
rom_assets_loaded_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ManageActiveEditors();
|
if (!current_rom_) {
|
||||||
|
DrawHomepage();
|
||||||
|
} else {
|
||||||
|
ManageActiveEditors();
|
||||||
|
}
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +299,7 @@ void EditorManager::ManageKeyboardShortcuts() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorManager::DrawStatusPopup() {
|
void EditorManager::DrawPopups() {
|
||||||
static absl::Status prev_status;
|
static absl::Status prev_status;
|
||||||
if (!status_.ok()) {
|
if (!status_.ok()) {
|
||||||
show_status_ = true;
|
show_status_ = true;
|
||||||
@@ -322,9 +325,7 @@ void EditorManager::DrawStatusPopup() {
|
|||||||
}
|
}
|
||||||
End();
|
End();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void EditorManager::DrawAboutPopup() {
|
|
||||||
if (about_) OpenPopup("About");
|
if (about_) OpenPopup("About");
|
||||||
if (BeginPopupModal("About", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
if (BeginPopupModal("About", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
Text("Yet Another Zelda3 Editor - v%s", version_.c_str());
|
Text("Yet Another Zelda3 Editor - v%s", version_.c_str());
|
||||||
@@ -339,9 +340,7 @@ void EditorManager::DrawAboutPopup() {
|
|||||||
}
|
}
|
||||||
EndPopup();
|
EndPopup();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void EditorManager::DrawInfoPopup() {
|
|
||||||
if (rom_info_) OpenPopup("ROM Information");
|
if (rom_info_) OpenPopup("ROM Information");
|
||||||
if (BeginPopupModal("ROM Information", nullptr,
|
if (BeginPopupModal("ROM Information", nullptr,
|
||||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
@@ -357,11 +356,29 @@ void EditorManager::DrawInfoPopup() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorManager::DrawYazeMenu() {
|
void EditorManager::DrawHomepage() {
|
||||||
|
TextWrapped("Welcome to the Yet Another Zelda3 Editor (yaze)!");
|
||||||
|
TextWrapped("This editor is designed to be a comprehensive tool for editing the Legend of Zelda: A Link to the Past.");
|
||||||
|
TextWrapped("The editor is still in development, so please report any bugs or issues you encounter.");
|
||||||
|
|
||||||
|
static bool managed_startup = false;
|
||||||
|
|
||||||
|
if (Button("Open ROM", ImVec2(200, 0))) {
|
||||||
|
LoadRom();
|
||||||
|
}
|
||||||
|
SameLine();
|
||||||
|
ImGui::Checkbox("Manage Startup", &managed_startup);
|
||||||
|
Separator();
|
||||||
|
|
||||||
|
settings_editor_.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorManager::DrawMenuBar() {
|
||||||
static bool show_display_settings = false;
|
static bool show_display_settings = false;
|
||||||
|
|
||||||
if (BeginMenuBar()) {
|
if (BeginMenuBar()) {
|
||||||
DrawYazeMenuBar();
|
DrawMenuContent();
|
||||||
|
|
||||||
SameLine(GetWindowWidth() - GetStyle().ItemSpacing.x -
|
SameLine(GetWindowWidth() - GetStyle().ItemSpacing.x -
|
||||||
CalcTextSize(ICON_MD_DISPLAY_SETTINGS).x - 110);
|
CalcTextSize(ICON_MD_DISPLAY_SETTINGS).x - 110);
|
||||||
PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||||
@@ -380,7 +397,7 @@ void EditorManager::DrawYazeMenu() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorManager::DrawYazeMenuBar() {
|
void EditorManager::DrawMenuContent() {
|
||||||
static bool save_as_menu = false;
|
static bool save_as_menu = false;
|
||||||
static bool new_project_menu = false;
|
static bool new_project_menu = false;
|
||||||
|
|
||||||
@@ -445,11 +462,23 @@ void EditorManager::DrawYazeMenuBar() {
|
|||||||
MenuItem("Backup ROM", "", &backup_rom_);
|
MenuItem("Backup ROM", "", &backup_rom_);
|
||||||
MenuItem("Save New Auto", "", &save_new_auto_);
|
MenuItem("Save New Auto", "", &save_new_auto_);
|
||||||
Separator();
|
Separator();
|
||||||
if (BeginMenu("Experiment Flags")) {
|
static FlagsMenu flags_menu;
|
||||||
static FlagsMenu flags_menu;
|
if (BeginMenu("System Flags")) {
|
||||||
flags_menu.Draw();
|
flags_menu.DrawSystemFlags();
|
||||||
EndMenu();
|
EndMenu();
|
||||||
}
|
}
|
||||||
|
if (BeginMenu("Overworld Flags")) {
|
||||||
|
flags_menu.DrawOverworldFlags();
|
||||||
|
EndMenu();
|
||||||
|
}
|
||||||
|
if (BeginMenu("Dungeon Flags")) {
|
||||||
|
flags_menu.DrawDungeonFlags();
|
||||||
|
EndMenu();
|
||||||
|
}
|
||||||
|
if (BeginMenu("Resource Flags")) {
|
||||||
|
flags_menu.DrawResourceFlags();
|
||||||
|
EndMenu();
|
||||||
|
}
|
||||||
EndMenu();
|
EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,10 +700,25 @@ void EditorManager::DrawYazeMenuBar() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorManager::DrawRomMenu() {
|
||||||
|
if (roms_.empty()) return;
|
||||||
|
|
||||||
|
// Dropdown in the center of the menu bar with ROMs
|
||||||
|
if (BeginMenu("ROM")) {
|
||||||
|
for (size_t i = 0; i < roms_.size(); ++i) {
|
||||||
|
if (MenuItem(roms_[i]->title().c_str())) {
|
||||||
|
current_rom_ = roms_[i].get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EditorManager::LoadRom() {
|
void EditorManager::LoadRom() {
|
||||||
auto file_name = FileDialogWrapper::ShowOpenFileDialog();
|
auto file_name = FileDialogWrapper::ShowOpenFileDialog();
|
||||||
auto load_rom = rom()->LoadFromFile(file_name);
|
auto load_rom = rom()->LoadFromFile(file_name);
|
||||||
if (load_rom.ok()) {
|
if (load_rom.ok()) {
|
||||||
|
current_rom_ = rom();
|
||||||
static RecentFilesManager manager("recent_files.txt");
|
static RecentFilesManager manager("recent_files.txt");
|
||||||
manager.Load();
|
manager.Load();
|
||||||
manager.AddFile(file_name);
|
manager.AddFile(file_name);
|
||||||
@@ -691,6 +735,10 @@ void EditorManager::SaveRom() {
|
|||||||
status_ = overworld_editor_.Save();
|
status_ = overworld_editor_.Save();
|
||||||
RETURN_VOID_IF_ERROR(status_);
|
RETURN_VOID_IF_ERROR(status_);
|
||||||
|
|
||||||
|
if (core::ExperimentFlags::get().kSaveGraphicsSheet)
|
||||||
|
PRINT_IF_ERROR(SaveAllGraphicsData(*rom(),
|
||||||
|
GraphicsSheetManager::GetInstance().gfx_sheets()));
|
||||||
|
|
||||||
status_ = rom()->SaveToFile(backup_rom_, save_new_auto_);
|
status_ = rom()->SaveToFile(backup_rom_, save_new_auto_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,11 +750,13 @@ void EditorManager::OpenRomOrProject(const std::string &filename) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
status_ = rom()->LoadFromFile(filename);
|
status_ = rom()->LoadFromFile(filename);
|
||||||
|
current_rom_ = rom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status EditorManager::OpenProject() {
|
absl::Status EditorManager::OpenProject() {
|
||||||
RETURN_IF_ERROR(rom()->LoadFromFile(current_project_.rom_filename_));
|
RETURN_IF_ERROR(rom()->LoadFromFile(current_project_.rom_filename_));
|
||||||
|
current_rom_ = rom();
|
||||||
|
|
||||||
if (!rom()->resource_label()->LoadLabels(current_project_.labels_filename_)) {
|
if (!rom()->resource_label()->LoadLabels(current_project_.labels_filename_)) {
|
||||||
return absl::InternalError(
|
return absl::InternalError(
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ class EditorManager : public SharedRom {
|
|||||||
active_editors_.push_back(&sprite_editor_);
|
active_editors_.push_back(&sprite_editor_);
|
||||||
active_editors_.push_back(&message_editor_);
|
active_editors_.push_back(&message_editor_);
|
||||||
active_editors_.push_back(&screen_editor_);
|
active_editors_.push_back(&screen_editor_);
|
||||||
|
active_editors_.push_back(&settings_editor_);
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << YAZE_VERSION_MAJOR << "." << YAZE_VERSION_MINOR << "."
|
ss << YAZE_VERSION_MAJOR << "." << YAZE_VERSION_MINOR << "."
|
||||||
<< YAZE_VERSION_PATCH;
|
<< YAZE_VERSION_PATCH;
|
||||||
@@ -56,18 +57,18 @@ class EditorManager : public SharedRom {
|
|||||||
absl::Status Update();
|
absl::Status Update();
|
||||||
|
|
||||||
auto emulator() -> emu::Emulator & { return emulator_; }
|
auto emulator() -> emu::Emulator & { return emulator_; }
|
||||||
auto quit() { return quit_; }
|
auto quit() const { return quit_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ManageActiveEditors();
|
void ManageActiveEditors();
|
||||||
void ManageKeyboardShortcuts();
|
void ManageKeyboardShortcuts();
|
||||||
|
|
||||||
void DrawStatusPopup();
|
void DrawPopups();
|
||||||
void DrawAboutPopup();
|
void DrawHomepage();
|
||||||
void DrawInfoPopup();
|
|
||||||
|
|
||||||
void DrawYazeMenu();
|
void DrawMenuBar();
|
||||||
void DrawYazeMenuBar();
|
void DrawMenuContent();
|
||||||
|
void DrawRomMenu();
|
||||||
|
|
||||||
void LoadRom();
|
void LoadRom();
|
||||||
void SaveRom();
|
void SaveRom();
|
||||||
@@ -88,6 +89,8 @@ class EditorManager : public SharedRom {
|
|||||||
absl::Status status_;
|
absl::Status status_;
|
||||||
emu::Emulator emulator_;
|
emu::Emulator emulator_;
|
||||||
std::vector<Editor *> active_editors_;
|
std::vector<Editor *> active_editors_;
|
||||||
|
std::vector<std::unique_ptr<Rom>> roms_;
|
||||||
|
Rom* current_rom_ = nullptr;
|
||||||
|
|
||||||
Project current_project_;
|
Project current_project_;
|
||||||
EditorContext editor_context_;
|
EditorContext editor_context_;
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ void GfxGroupEditor::DrawBlocksetViewer(bool sheet_only) {
|
|||||||
BeginGroup();
|
BeginGroup();
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
int sheet_id = rom()->main_blockset_ids[selected_blockset_][i];
|
int sheet_id = rom()->main_blockset_ids[selected_blockset_][i];
|
||||||
auto sheet = rom()->gfx_sheets().at(sheet_id);
|
auto &sheet = GraphicsSheetManager::GetInstance().mutable_gfx_sheets()->at(sheet_id);
|
||||||
gui::BitmapCanvasPipeline(blockset_canvas_, sheet, 256, 0x10 * 0x04,
|
gui::BitmapCanvasPipeline(blockset_canvas_, sheet, 256, 0x10 * 0x04,
|
||||||
0x20, true, false, 22);
|
0x20, true, false, 22);
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ void GfxGroupEditor::DrawRoomsetViewer() {
|
|||||||
BeginGroup();
|
BeginGroup();
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
int sheet_id = rom()->room_blockset_ids[selected_roomset_][i];
|
int sheet_id = rom()->room_blockset_ids[selected_roomset_][i];
|
||||||
auto sheet = rom()->gfx_sheets().at(sheet_id);
|
auto &sheet = GraphicsSheetManager::GetInstance().mutable_gfx_sheets()->at(sheet_id);
|
||||||
gui::BitmapCanvasPipeline(roomset_canvas_, sheet, 256, 0x10 * 0x04,
|
gui::BitmapCanvasPipeline(roomset_canvas_, sheet, 256, 0x10 * 0x04,
|
||||||
0x20, true, false, 23);
|
0x20, true, false, 23);
|
||||||
}
|
}
|
||||||
@@ -203,7 +203,7 @@ void GfxGroupEditor::DrawSpritesetViewer(bool sheet_only) {
|
|||||||
BeginGroup();
|
BeginGroup();
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
int sheet_id = rom()->spriteset_ids[selected_spriteset_][i];
|
int sheet_id = rom()->spriteset_ids[selected_spriteset_][i];
|
||||||
auto sheet = rom()->gfx_sheets().at(115 + sheet_id);
|
auto &sheet = GraphicsSheetManager::GetInstance().mutable_gfx_sheets()->at(115 + sheet_id);
|
||||||
gui::BitmapCanvasPipeline(spriteset_canvas_, sheet, 256, 0x10 * 0x04,
|
gui::BitmapCanvasPipeline(spriteset_canvas_, sheet, 256, 0x10 * 0x04,
|
||||||
0x20, true, false, 24);
|
0x20, true, false, 24);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ absl::Status GraphicsEditor::Update() {
|
|||||||
status_ = UpdateGfxEdit();
|
status_ = UpdateGfxEdit();
|
||||||
TAB_ITEM("Sheet Browser")
|
TAB_ITEM("Sheet Browser")
|
||||||
if (asset_browser_.Initialized == false) {
|
if (asset_browser_.Initialized == false) {
|
||||||
asset_browser_.Initialize(rom()->gfx_sheets());
|
asset_browser_.Initialize(GraphicsSheetManager::GetInstance().gfx_sheets());
|
||||||
}
|
}
|
||||||
asset_browser_.Draw(rom()->gfx_sheets());
|
asset_browser_.Draw(GraphicsSheetManager::GetInstance().gfx_sheets());
|
||||||
END_TAB_ITEM()
|
END_TAB_ITEM()
|
||||||
status_ = UpdateScadView();
|
status_ = UpdateScadView();
|
||||||
status_ = UpdateLinkGfxView();
|
status_ = UpdateLinkGfxView();
|
||||||
@@ -117,7 +117,7 @@ void GraphicsEditor::DrawGfxEditToolset() {
|
|||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
if (Button(ICON_MD_CONTENT_COPY)) {
|
if (Button(ICON_MD_CONTENT_COPY)) {
|
||||||
std::vector<uint8_t> png_data =
|
std::vector<uint8_t> png_data =
|
||||||
rom()->gfx_sheets().at(current_sheet_).GetPngData();
|
GraphicsSheetManager::GetInstance().gfx_sheets().at(current_sheet_).GetPngData();
|
||||||
core::CopyImageToClipboard(png_data);
|
core::CopyImageToClipboard(png_data);
|
||||||
}
|
}
|
||||||
HOVER_HINT("Copy to Clipboard");
|
HOVER_HINT("Copy to Clipboard");
|
||||||
@@ -128,12 +128,11 @@ void GraphicsEditor::DrawGfxEditToolset() {
|
|||||||
int width, height;
|
int width, height;
|
||||||
core::GetImageFromClipboard(png_data, width, height);
|
core::GetImageFromClipboard(png_data, width, height);
|
||||||
if (png_data.size() > 0) {
|
if (png_data.size() > 0) {
|
||||||
rom()
|
GraphicsSheetManager::GetInstance().mutable_gfx_sheets()
|
||||||
->mutable_gfx_sheets()
|
|
||||||
->at(current_sheet_)
|
->at(current_sheet_)
|
||||||
.Create(width, height, 8, png_data);
|
.Create(width, height, 8, png_data);
|
||||||
Renderer::GetInstance().UpdateBitmap(
|
Renderer::GetInstance().UpdateBitmap(
|
||||||
&rom()->mutable_gfx_sheets()->at(current_sheet_));
|
&GraphicsSheetManager::GetInstance().mutable_gfx_sheets()->at(current_sheet_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HOVER_HINT("Paste from Clipboard");
|
HOVER_HINT("Paste from Clipboard");
|
||||||
@@ -153,9 +152,9 @@ void GraphicsEditor::DrawGfxEditToolset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
auto bitmap = rom()->gfx_sheets()[current_sheet_];
|
auto bitmap = GraphicsSheetManager::GetInstance().gfx_sheets()[current_sheet_];
|
||||||
auto palette = bitmap.palette();
|
auto palette = bitmap.palette();
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < palette.size(); i++) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
auto color =
|
auto color =
|
||||||
ImVec4(palette[i].rgb().x / 255.0f, palette[i].rgb().y / 255.0f,
|
ImVec4(palette[i].rgb().x / 255.0f, palette[i].rgb().y / 255.0f,
|
||||||
@@ -192,7 +191,7 @@ absl::Status GraphicsEditor::UpdateGfxSheetList() {
|
|||||||
(int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped.
|
(int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped.
|
||||||
|
|
||||||
int key = 0;
|
int key = 0;
|
||||||
for (auto& value : rom()->gfx_sheets()) {
|
for (auto& value : GraphicsSheetManager::GetInstance().gfx_sheets()) {
|
||||||
ImGui::BeginChild(absl::StrFormat("##GfxSheet%02X", key).c_str(),
|
ImGui::BeginChild(absl::StrFormat("##GfxSheet%02X", key).c_str(),
|
||||||
ImVec2(0x100 + 1, 0x40 + 1), true,
|
ImVec2(0x100 + 1, 0x40 + 1), true,
|
||||||
ImGuiWindowFlags_NoDecoration);
|
ImGuiWindowFlags_NoDecoration);
|
||||||
@@ -281,7 +280,7 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
|||||||
ImGuiWindowFlags_AlwaysVerticalScrollbar |
|
ImGuiWindowFlags_AlwaysVerticalScrollbar |
|
||||||
ImGuiWindowFlags_AlwaysHorizontalScrollbar);
|
ImGuiWindowFlags_AlwaysHorizontalScrollbar);
|
||||||
|
|
||||||
gfx::Bitmap& current_bitmap = rom()->mutable_gfx_sheets()->at(sheet_id);
|
gfx::Bitmap& current_bitmap = GraphicsSheetManager::GetInstance().mutable_gfx_sheets()->at(sheet_id);
|
||||||
|
|
||||||
auto draw_tile_event = [&]() {
|
auto draw_tile_event = [&]() {
|
||||||
current_sheet_canvas_.DrawTileOnBitmap(tile_size_, ¤t_bitmap,
|
current_sheet_canvas_.DrawTileOnBitmap(tile_size_, ¤t_bitmap,
|
||||||
@@ -290,7 +289,7 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
current_sheet_canvas_.UpdateColorPainter(
|
current_sheet_canvas_.UpdateColorPainter(
|
||||||
rom()->mutable_gfx_sheets()->at(sheet_id), current_color_,
|
GraphicsSheetManager::GetInstance().mutable_gfx_sheets()->at(sheet_id), current_color_,
|
||||||
draw_tile_event, tile_size_, current_scale_);
|
draw_tile_event, tile_size_, current_scale_);
|
||||||
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
@@ -323,7 +322,7 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
|||||||
current_sheet_ = id;
|
current_sheet_ = id;
|
||||||
// ImVec2(0x100, 0x40),
|
// ImVec2(0x100, 0x40),
|
||||||
current_sheet_canvas_.UpdateColorPainter(
|
current_sheet_canvas_.UpdateColorPainter(
|
||||||
rom()->mutable_gfx_sheets()->at(id), current_color_,
|
GraphicsSheetManager::GetInstance().mutable_gfx_sheets()->at(id), current_color_,
|
||||||
[&]() {
|
[&]() {
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -360,12 +359,11 @@ absl::Status GraphicsEditor::UpdatePaletteColumn() {
|
|||||||
|
|
||||||
if (refresh_graphics_ && !open_sheets_.empty()) {
|
if (refresh_graphics_ && !open_sheets_.empty()) {
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom()
|
GraphicsSheetManager::GetInstance().mutable_gfx_sheets()
|
||||||
->mutable_gfx_sheets()
|
|
||||||
->data()[current_sheet_]
|
->data()[current_sheet_]
|
||||||
.ApplyPaletteWithTransparent(palette, edit_palette_sub_index_));
|
.ApplyPaletteWithTransparent(palette, edit_palette_sub_index_));
|
||||||
Renderer::GetInstance().UpdateBitmap(
|
Renderer::GetInstance().UpdateBitmap(
|
||||||
&rom()->mutable_gfx_sheets()->data()[current_sheet_]);
|
&GraphicsSheetManager::GetInstance().mutable_gfx_sheets()->data()[current_sheet_]);
|
||||||
refresh_graphics_ = false;
|
refresh_graphics_ = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -387,7 +385,7 @@ absl::Status GraphicsEditor::UpdateLinkGfxView() {
|
|||||||
link_canvas_.DrawGrid(16.0f);
|
link_canvas_.DrawGrid(16.0f);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto link_sheet : *rom()->mutable_link_graphics()) {
|
for (auto& link_sheet : link_sheets_) {
|
||||||
int x_offset = 0;
|
int x_offset = 0;
|
||||||
int y_offset = gfx::kTilesheetHeight * i * 4;
|
int y_offset = gfx::kTilesheetHeight * i * 4;
|
||||||
link_canvas_.DrawContextMenu(&link_sheet);
|
link_canvas_.DrawContextMenu(&link_sheet);
|
||||||
@@ -404,7 +402,7 @@ absl::Status GraphicsEditor::UpdateLinkGfxView() {
|
|||||||
if (ImGui::Button("Load Link Graphics (Experimental)")) {
|
if (ImGui::Button("Load Link Graphics (Experimental)")) {
|
||||||
if (rom()->is_loaded()) {
|
if (rom()->is_loaded()) {
|
||||||
// Load Links graphics from the ROM
|
// Load Links graphics from the ROM
|
||||||
RETURN_IF_ERROR(rom()->LoadLinkGraphics());
|
ASSIGN_OR_RETURN(link_sheets_, LoadLinkGraphics(*rom()));
|
||||||
|
|
||||||
// Split it into the pose data frames
|
// Split it into the pose data frames
|
||||||
// Create an animation step display for the poses
|
// Create an animation step display for the poses
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ class GraphicsEditor : public SharedRom, public Editor {
|
|||||||
|
|
||||||
Rom temp_rom_;
|
Rom temp_rom_;
|
||||||
Rom tilemap_rom_;
|
Rom tilemap_rom_;
|
||||||
zelda3::Overworld overworld_;
|
zelda3::Overworld overworld_{ temp_rom_ };
|
||||||
MemoryEditor cgx_memory_editor_;
|
MemoryEditor cgx_memory_editor_;
|
||||||
MemoryEditor col_memory_editor_;
|
MemoryEditor col_memory_editor_;
|
||||||
PaletteEditor palette_editor_;
|
PaletteEditor palette_editor_;
|
||||||
@@ -176,6 +176,7 @@ class GraphicsEditor : public SharedRom, public Editor {
|
|||||||
gfx::Bitmap bin_bitmap_;
|
gfx::Bitmap bin_bitmap_;
|
||||||
gfx::Bitmap link_full_sheet_;
|
gfx::Bitmap link_full_sheet_;
|
||||||
std::array<gfx::Bitmap, kNumGfxSheets> gfx_sheets_;
|
std::array<gfx::Bitmap, kNumGfxSheets> gfx_sheets_;
|
||||||
|
std::array<gfx::Bitmap, kNumLinkSheets> link_sheets_;
|
||||||
|
|
||||||
gfx::PaletteGroup col_file_palette_group_;
|
gfx::PaletteGroup col_file_palette_group_;
|
||||||
gfx::SnesPalette z3_rom_palette_;
|
gfx::SnesPalette z3_rom_palette_;
|
||||||
|
|||||||
@@ -383,10 +383,10 @@ void ScreenEditor::DrawDungeonMapsEditor() {
|
|||||||
|
|
||||||
if (LoadDungeonMapTile16(rom()->graphics_buffer()).ok()) {
|
if (LoadDungeonMapTile16(rom()->graphics_buffer()).ok()) {
|
||||||
// TODO: Load roomset gfx based on dungeon ID
|
// TODO: Load roomset gfx based on dungeon ID
|
||||||
sheets_.emplace(0, rom()->gfx_sheets()[212]);
|
sheets_.emplace(0, GraphicsSheetManager::GetInstance().gfx_sheets()[212]);
|
||||||
sheets_.emplace(1, rom()->gfx_sheets()[213]);
|
sheets_.emplace(1, GraphicsSheetManager::GetInstance().gfx_sheets()[213]);
|
||||||
sheets_.emplace(2, rom()->gfx_sheets()[214]);
|
sheets_.emplace(2, GraphicsSheetManager::GetInstance().gfx_sheets()[214]);
|
||||||
sheets_.emplace(3, rom()->gfx_sheets()[215]);
|
sheets_.emplace(3, GraphicsSheetManager::GetInstance().gfx_sheets()[215]);
|
||||||
int current_tile8 = 0;
|
int current_tile8 = 0;
|
||||||
int tile_data_offset = 0;
|
int tile_data_offset = 0;
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
|||||||
@@ -43,12 +43,12 @@ using ImGui::Text;
|
|||||||
|
|
||||||
absl::Status Tile16Editor::InitBlockset(
|
absl::Status Tile16Editor::InitBlockset(
|
||||||
const gfx::Bitmap &tile16_blockset_bmp, const gfx::Bitmap ¤t_gfx_bmp,
|
const gfx::Bitmap &tile16_blockset_bmp, const gfx::Bitmap ¤t_gfx_bmp,
|
||||||
const std::vector<gfx::Bitmap> &tile16_individual,
|
|
||||||
std::array<uint8_t, 0x200> &all_tiles_types) {
|
std::array<uint8_t, 0x200> &all_tiles_types) {
|
||||||
all_tiles_types_ = all_tiles_types;
|
all_tiles_types_ = all_tiles_types;
|
||||||
tile16_blockset_bmp_ = tile16_blockset_bmp;
|
tile16_blockset_bmp_ = tile16_blockset_bmp;
|
||||||
tile16_individual_ = tile16_individual;
|
current_gfx_bmp_.Create(current_gfx_bmp.width(), current_gfx_bmp.height(),
|
||||||
current_gfx_bmp_ = current_gfx_bmp;
|
current_gfx_bmp.depth(), current_gfx_bmp.vector());
|
||||||
|
core::Renderer::GetInstance().RenderBitmap(&tile16_blockset_bmp_);
|
||||||
RETURN_IF_ERROR(LoadTile8());
|
RETURN_IF_ERROR(LoadTile8());
|
||||||
ImVector<std::string> tile16_names;
|
ImVector<std::string> tile16_names;
|
||||||
for (int i = 0; i < 0x200; ++i) {
|
for (int i = 0; i < 0x200; ++i) {
|
||||||
@@ -373,7 +373,7 @@ absl::Status Tile16Editor::UpdateTransferTileCanvas() {
|
|||||||
|
|
||||||
// TODO: Implement tile16 transfer
|
// TODO: Implement tile16 transfer
|
||||||
if (transfer_started_ && !transfer_blockset_loaded_) {
|
if (transfer_started_ && !transfer_blockset_loaded_) {
|
||||||
PRINT_IF_ERROR(transfer_rom_.LoadAllGraphicsData())
|
ASSIGN_OR_RETURN(transfer_gfx_, LoadAllGraphicsData(transfer_rom_))
|
||||||
|
|
||||||
// Load the Link to the Past overworld.
|
// Load the Link to the Past overworld.
|
||||||
PRINT_IF_ERROR(transfer_overworld_.Load(transfer_rom_))
|
PRINT_IF_ERROR(transfer_overworld_.Load(transfer_rom_))
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#ifndef YAZE_APP_EDITOR_TILE16EDITOR_H
|
#ifndef YAZE_APP_EDITOR_TILE16EDITOR_H
|
||||||
#define YAZE_APP_EDITOR_TILE16EDITOR_H
|
#define YAZE_APP_EDITOR_TILE16EDITOR_H
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "app/core/common.h"
|
#include "app/core/common.h"
|
||||||
#include "app/editor/graphics/palette_editor.h"
|
#include "app/editor/graphics/palette_editor.h"
|
||||||
@@ -20,9 +23,9 @@ namespace editor {
|
|||||||
*/
|
*/
|
||||||
class Tile16Editor : public gfx::GfxContext, public SharedRom {
|
class Tile16Editor : public gfx::GfxContext, public SharedRom {
|
||||||
public:
|
public:
|
||||||
|
Tile16Editor(std::array<gfx::Bitmap, zelda3::kNumTile16Individual>& tile16_individual) : tile16_individual_(tile16_individual) {}
|
||||||
absl::Status InitBlockset(const gfx::Bitmap &tile16_blockset_bmp,
|
absl::Status InitBlockset(const gfx::Bitmap &tile16_blockset_bmp,
|
||||||
const gfx::Bitmap ¤t_gfx_bmp,
|
const gfx::Bitmap ¤t_gfx_bmp,
|
||||||
const std::vector<gfx::Bitmap> &tile16_individual,
|
|
||||||
std::array<uint8_t, 0x200> &all_tiles_types);
|
std::array<uint8_t, 0x200> &all_tiles_types);
|
||||||
|
|
||||||
absl::Status Update();
|
absl::Status Update();
|
||||||
@@ -82,17 +85,17 @@ class Tile16Editor : public gfx::GfxContext, public SharedRom {
|
|||||||
gui::Canvas transfer_canvas_;
|
gui::Canvas transfer_canvas_;
|
||||||
gfx::Bitmap transfer_blockset_bmp_;
|
gfx::Bitmap transfer_blockset_bmp_;
|
||||||
|
|
||||||
std::vector<gfx::Bitmap> tile16_individual_;
|
std::array<gfx::Bitmap, zelda3::kNumTile16Individual>& tile16_individual_;
|
||||||
std::vector<gfx::Bitmap> current_gfx_individual_;
|
std::vector<gfx::Bitmap> current_gfx_individual_;
|
||||||
|
|
||||||
PaletteEditor palette_editor_;
|
PaletteEditor palette_editor_;
|
||||||
|
|
||||||
gfx::SnesPalette palette_;
|
gfx::SnesPalette palette_;
|
||||||
zelda3::Overworld transfer_overworld_;
|
|
||||||
|
|
||||||
absl::Status status_;
|
absl::Status status_;
|
||||||
|
|
||||||
Rom transfer_rom_;
|
Rom transfer_rom_;
|
||||||
|
zelda3::Overworld transfer_overworld_{ transfer_rom_ };
|
||||||
|
std::array<gfx::Bitmap, kNumGfxSheets> transfer_gfx_;
|
||||||
absl::Status transfer_status_;
|
absl::Status transfer_status_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -44,11 +44,11 @@ uint8_t FindDictionaryEntry(uint8_t value);
|
|||||||
std::vector<uint8_t> ParseMessageToData(std::string str);
|
std::vector<uint8_t> ParseMessageToData(std::string str);
|
||||||
|
|
||||||
struct DictionaryEntry {
|
struct DictionaryEntry {
|
||||||
uint8_t ID;
|
uint8_t ID = 0;
|
||||||
std::string Contents;
|
std::string Contents = "";
|
||||||
std::vector<uint8_t> Data;
|
std::vector<uint8_t> Data;
|
||||||
int Length;
|
int Length = 0;
|
||||||
std::string Token;
|
std::string Token = "";
|
||||||
|
|
||||||
DictionaryEntry() = default;
|
DictionaryEntry() = default;
|
||||||
DictionaryEntry(uint8_t i, std::string s)
|
DictionaryEntry(uint8_t i, std::string s)
|
||||||
@@ -57,11 +57,11 @@ struct DictionaryEntry {
|
|||||||
Data = ParseMessageToData(Contents);
|
Data = ParseMessageToData(Contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ContainedInString(std::string s) {
|
bool ContainedInString(std::string s) const {
|
||||||
return s.find(Contents) != std::string::npos;
|
return s.find(Contents) != std::string::npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ReplaceInstancesOfIn(std::string s) {
|
std::string ReplaceInstancesOfIn(std::string s) const {
|
||||||
std::string replacedString = s;
|
std::string replacedString = s;
|
||||||
size_t pos = replacedString.find(Contents);
|
size_t pos = replacedString.find(Contents);
|
||||||
while (pos != std::string::npos) {
|
while (pos != std::string::npos) {
|
||||||
@@ -86,8 +86,8 @@ std::string ReplaceAllDictionaryWords(std::string str,
|
|||||||
const std::string CHEESE = "\uBEBE";
|
const std::string CHEESE = "\uBEBE";
|
||||||
|
|
||||||
struct MessageData {
|
struct MessageData {
|
||||||
int ID;
|
int ID = 0;
|
||||||
int Address;
|
int Address = 0;
|
||||||
std::string RawString;
|
std::string RawString;
|
||||||
std::string ContentsParsed;
|
std::string ContentsParsed;
|
||||||
std::vector<uint8_t> Data;
|
std::vector<uint8_t> Data;
|
||||||
@@ -115,7 +115,7 @@ struct MessageData {
|
|||||||
ContentsParsed = other.ContentsParsed;
|
ContentsParsed = other.ContentsParsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString() {
|
std::string ToString() const {
|
||||||
return absl::StrFormat("%0X - %s", ID, ContentsParsed);
|
return absl::StrFormat("%0X - %s", ID, ContentsParsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,8 +163,8 @@ struct TextElement {
|
|||||||
bool HasArgument;
|
bool HasArgument;
|
||||||
|
|
||||||
TextElement() = default;
|
TextElement() = default;
|
||||||
TextElement(uint8_t id, std::string token, bool arg,
|
TextElement(uint8_t id, const std::string& token, bool arg,
|
||||||
std::string description) {
|
const std::string& description) {
|
||||||
ID = id;
|
ID = id;
|
||||||
Token = token;
|
Token = token;
|
||||||
if (arg) {
|
if (arg) {
|
||||||
@@ -181,7 +181,7 @@ struct TextElement {
|
|||||||
StrictPattern = "^" + Pattern + "$";
|
StrictPattern = "^" + Pattern + "$";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetParameterizedToken(uint8_t value = 0) {
|
std::string GetParameterizedToken(uint8_t value = 0) const {
|
||||||
if (HasArgument) {
|
if (HasArgument) {
|
||||||
return absl::StrFormat("[%s:%02X]", Token, value);
|
return absl::StrFormat("[%s:%02X]", Token, value);
|
||||||
} else {
|
} else {
|
||||||
@@ -189,7 +189,7 @@ struct TextElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToString() {
|
std::string ToString() const {
|
||||||
return absl::StrFormat("%s %s", GenericToken, Description);
|
return absl::StrFormat("%s %s", GenericToken, Description);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,37 +200,61 @@ struct TextElement {
|
|||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Empty() { return ID == 0; }
|
bool Empty() const { return ID == 0; }
|
||||||
|
|
||||||
// Comparison operator
|
// Comparison operator
|
||||||
bool operator==(const TextElement& other) const { return ID == other.ID; }
|
bool operator==(const TextElement& other) const { return ID == other.ID; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const static std::string kWindowBorder = "Window border";
|
||||||
|
const static std::string kWindowPosition = "Window position";
|
||||||
|
const static std::string kScrollSpeed = "Scroll speed";
|
||||||
|
const static std::string kTextDrawSpeed = "Text draw speed";
|
||||||
|
const static std::string kTextColor = "Text color";
|
||||||
|
const static std::string kPlayerName = "Player name";
|
||||||
|
const static std::string kLine1Str = "Line 1";
|
||||||
|
const static std::string kLine2Str = "Line 2";
|
||||||
|
const static std::string kLine3Str = "Line 3";
|
||||||
|
const static std::string kWaitForKey = "Wait for key";
|
||||||
|
const static std::string kScrollText = "Scroll text";
|
||||||
|
const static std::string kDelayX = "Delay X";
|
||||||
|
const static std::string kBCDNumber = "BCD number";
|
||||||
|
const static std::string kSoundEffect = "Sound effect";
|
||||||
|
const static std::string kChoose3 = "Choose 3";
|
||||||
|
const static std::string kChoose2High = "Choose 2 high";
|
||||||
|
const static std::string kChoose2Low = "Choose 2 low";
|
||||||
|
const static std::string kChoose2Indented = "Choose 2 indented";
|
||||||
|
const static std::string kChooseItem = "Choose item";
|
||||||
|
const static std::string kNextAttractImage = "Next attract image";
|
||||||
|
const static std::string kBankMarker = "Bank marker (automatic)";
|
||||||
|
const static std::string kCrash = "Crash";
|
||||||
|
|
||||||
static const std::vector<TextElement> TextCommands = {
|
static const std::vector<TextElement> TextCommands = {
|
||||||
TextElement(0x6B, "W", true, "Window border"),
|
TextElement(0x6B, "W", true, kWindowBorder),
|
||||||
TextElement(0x6D, "P", true, "Window position"),
|
TextElement(0x6D, "P", true, kWindowPosition),
|
||||||
TextElement(0x6E, "SPD", true, "Scroll speed"),
|
TextElement(0x6E, "SPD", true, kScrollSpeed),
|
||||||
TextElement(0x7A, "S", true, "Text draw speed"),
|
TextElement(0x7A, "S", true, kTextDrawSpeed),
|
||||||
TextElement(0x77, "C", true, "Text color"),
|
TextElement(0x77, "C", true, kTextColor),
|
||||||
TextElement(0x6A, "L", false, "Player name"),
|
TextElement(0x6A, "L", false, kPlayerName),
|
||||||
TextElement(0x74, "1", false, "Line 1"),
|
TextElement(0x74, "1", false, kLine1Str),
|
||||||
TextElement(0x75, "2", false, "Line 2"),
|
TextElement(0x75, "2", false, kLine2Str),
|
||||||
TextElement(0x76, "3", false, "Line 3"),
|
TextElement(0x76, "3", false, kLine3Str),
|
||||||
TextElement(0x7E, "K", false, "Wait for key"),
|
TextElement(0x7E, "K", false, kWaitForKey),
|
||||||
TextElement(0x73, "V", false, "Scroll text"),
|
TextElement(0x73, "V", false, kScrollText),
|
||||||
TextElement(0x78, "WT", true, "Delay X"),
|
TextElement(0x78, "WT", true, kDelayX),
|
||||||
TextElement(0x6C, "N", true, "BCD number"),
|
TextElement(0x6C, "N", true, kBCDNumber),
|
||||||
TextElement(0x79, "SFX", true, "Sound effect"),
|
TextElement(0x79, "SFX", true, kSoundEffect),
|
||||||
TextElement(0x71, "CH3", false, "Choose 3"),
|
TextElement(0x71, "CH3", false, kChoose3),
|
||||||
TextElement(0x72, "CH2", false, "Choose 2 high"),
|
TextElement(0x72, "CH2", false, kChoose2High),
|
||||||
TextElement(0x6F, "CH2L", false, "Choose 2 low"),
|
TextElement(0x6F, "CH2L", false, kChoose2Low),
|
||||||
TextElement(0x68, "CH2I", false, "Choose 2 indented"),
|
TextElement(0x68, "CH2I", false, kChoose2Indented),
|
||||||
TextElement(0x69, "CHI", false, "Choose item"),
|
TextElement(0x69, "CHI", false, kChooseItem),
|
||||||
TextElement(0x67, "IMG", false, "Next attract image"),
|
TextElement(0x67, "IMG", false, kNextAttractImage),
|
||||||
TextElement(0x80, BANKToken, false, "Bank marker (automatic)"),
|
TextElement(0x80, BANKToken, false, kBankMarker),
|
||||||
TextElement(0x70, "NONO", false, "Crash"),
|
TextElement(0x70, "NONO", false, kCrash),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
TextElement FindMatchingCommand(uint8_t b);
|
TextElement FindMatchingCommand(uint8_t b);
|
||||||
|
|
||||||
static const std::vector<TextElement> SpecialChars = {
|
static const std::vector<TextElement> SpecialChars = {
|
||||||
|
|||||||
@@ -626,7 +626,7 @@ absl::Status MessageEditor::Save() {
|
|||||||
std::vector<uint8_t> backup = rom()->vector();
|
std::vector<uint8_t> backup = rom()->vector();
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
RETURN_IF_ERROR(rom()->Write(kCharactersWidth + i, width_array[i]));
|
RETURN_IF_ERROR(rom()->WriteByte(kCharactersWidth + i, width_array[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
int pos = kTextData;
|
int pos = kTextData;
|
||||||
@@ -634,7 +634,7 @@ absl::Status MessageEditor::Save() {
|
|||||||
|
|
||||||
for (const auto& message : list_of_texts_) {
|
for (const auto& message : list_of_texts_) {
|
||||||
for (const auto value : message.Data) {
|
for (const auto value : message.Data) {
|
||||||
RETURN_IF_ERROR(rom()->Write(pos, value));
|
RETURN_IF_ERROR(rom()->WriteByte(pos, value));
|
||||||
|
|
||||||
if (value == kBlockTerminator) {
|
if (value == kBlockTerminator) {
|
||||||
// Make sure we didn't go over the space available in the first block.
|
// Make sure we didn't go over the space available in the first block.
|
||||||
@@ -652,7 +652,7 @@ absl::Status MessageEditor::Save() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom()->Write(pos++, kMessageTerminator)); // , true, "Terminator text"
|
rom()->WriteByte(pos++, kMessageTerminator)); // , true, "Terminator text"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that we didn't go over the space available for the second block.
|
// Verify that we didn't go over the space available for the second block.
|
||||||
@@ -662,7 +662,7 @@ absl::Status MessageEditor::Save() {
|
|||||||
return absl::InternalError(DisplayTextOverflowError(pos, false));
|
return absl::InternalError(DisplayTextOverflowError(pos, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_IF_ERROR(rom()->Write(pos, 0xFF)); // , true, "End of text"
|
RETURN_IF_ERROR(rom()->WriteByte(pos, 0xFF)); // , true, "End of text"
|
||||||
|
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef YAZE_APP_EDITOR_MESSAGE_EDITOR_H
|
#ifndef YAZE_APP_EDITOR_MESSAGE_EDITOR_H
|
||||||
#define YAZE_APP_EDITOR_MESSAGE_EDITOR_H
|
#define YAZE_APP_EDITOR_MESSAGE_EDITOR_H
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -81,16 +82,13 @@ class MessageEditor : public Editor, public SharedRom {
|
|||||||
int text_position_ = 0;
|
int text_position_ = 0;
|
||||||
int shown_lines_ = 0;
|
int shown_lines_ = 0;
|
||||||
|
|
||||||
uint8_t width_array[kWidthArraySize];
|
|
||||||
|
|
||||||
std::string search_text_ = "";
|
std::string search_text_ = "";
|
||||||
|
|
||||||
|
std::array<uint8_t, kWidthArraySize> width_array = {0};
|
||||||
std::vector<uint8_t> font_gfx16_data_;
|
std::vector<uint8_t> font_gfx16_data_;
|
||||||
std::vector<uint8_t> current_font_gfx16_data_;
|
std::vector<uint8_t> current_font_gfx16_data_;
|
||||||
std::vector<std::string> parsed_messages_;
|
std::vector<std::string> parsed_messages_;
|
||||||
|
|
||||||
std::vector<MessageData> list_of_texts_;
|
std::vector<MessageData> list_of_texts_;
|
||||||
|
|
||||||
std::vector<DictionaryEntry> all_dictionaries_;
|
std::vector<DictionaryEntry> all_dictionaries_;
|
||||||
|
|
||||||
MessageData current_message_;
|
MessageData current_message_;
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ absl::Status OverworldEditor::Update() {
|
|||||||
status_ = absl::OkStatus();
|
status_ = absl::OkStatus();
|
||||||
if (rom_.is_loaded() && !all_gfx_loaded_) {
|
if (rom_.is_loaded() && !all_gfx_loaded_) {
|
||||||
RETURN_IF_ERROR(tile16_editor_.InitBlockset(
|
RETURN_IF_ERROR(tile16_editor_.InitBlockset(
|
||||||
tile16_blockset_bmp_, current_gfx_bmp_, tile16_individual_,
|
tile16_blockset_bmp_, current_gfx_bmp_,
|
||||||
*overworld_.mutable_all_tiles_types()));
|
*overworld_.mutable_all_tiles_types()));
|
||||||
ASSIGN_OR_RETURN(entrance_tiletypes_, zelda3::LoadEntranceTileTypes(rom_));
|
ASSIGN_OR_RETURN(entrance_tiletypes_, zelda3::LoadEntranceTileTypes(rom_));
|
||||||
all_gfx_loaded_ = true;
|
all_gfx_loaded_ = true;
|
||||||
@@ -417,7 +417,7 @@ void OverworldEditor::DrawOverworldEdits() {
|
|||||||
|
|
||||||
// Render the updated map bitmap.
|
// Render the updated map bitmap.
|
||||||
RenderUpdatedMapBitmap(mouse_position,
|
RenderUpdatedMapBitmap(mouse_position,
|
||||||
tile16_individual_data_[current_tile16_]);
|
tile16_individual_[current_tile16_].vector());
|
||||||
|
|
||||||
// Calculate the correct superX and superY values
|
// Calculate the correct superX and superY values
|
||||||
int superY = current_map_ / 8;
|
int superY = current_map_ / 8;
|
||||||
@@ -706,7 +706,7 @@ void OverworldEditor::DrawTile8Selector() {
|
|||||||
graphics_bin_canvas_.DrawContextMenu();
|
graphics_bin_canvas_.DrawContextMenu();
|
||||||
if (all_gfx_loaded_) {
|
if (all_gfx_loaded_) {
|
||||||
int key = 0;
|
int key = 0;
|
||||||
for (auto &value : rom_.gfx_sheets()) {
|
for (auto &value : GraphicsSheetManager::GetInstance().gfx_sheets()) {
|
||||||
int offset = 0x40 * (key + 1);
|
int offset = 0x40 * (key + 1);
|
||||||
int top_left_y = graphics_bin_canvas_.zero_point().y + 2;
|
int top_left_y = graphics_bin_canvas_.zero_point().y + 2;
|
||||||
if (key >= 1) {
|
if (key >= 1) {
|
||||||
@@ -1031,15 +1031,18 @@ absl::Status OverworldEditor::Save() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::Status OverworldEditor::LoadGraphics() {
|
absl::Status OverworldEditor::LoadGraphics() {
|
||||||
|
core::logf("Loading overworld.");
|
||||||
// Load the Link to the Past overworld.
|
// Load the Link to the Past overworld.
|
||||||
RETURN_IF_ERROR(overworld_.Load(rom_))
|
RETURN_IF_ERROR(overworld_.Load(rom_))
|
||||||
palette_ = overworld_.current_area_palette();
|
palette_ = overworld_.current_area_palette();
|
||||||
|
|
||||||
|
core::logf("Loading overworld graphics.");
|
||||||
// Create the area graphics image
|
// Create the area graphics image
|
||||||
RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
|
RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
|
||||||
0x80, kOverworldMapSize, 0x40, overworld_.current_graphics(),
|
0x80, kOverworldMapSize, 0x40, overworld_.current_graphics(),
|
||||||
current_gfx_bmp_, palette_));
|
current_gfx_bmp_, palette_));
|
||||||
|
|
||||||
|
core::logf("Loading overworld tileset.");
|
||||||
// Create the tile16 blockset image
|
// Create the tile16 blockset image
|
||||||
RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
|
RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
|
||||||
0x80, 0x2000, 0x08, overworld_.tile16_blockset_data(),
|
0x80, 0x2000, 0x08, overworld_.tile16_blockset_data(),
|
||||||
@@ -1048,38 +1051,42 @@ absl::Status OverworldEditor::LoadGraphics() {
|
|||||||
|
|
||||||
// Copy the tile16 data into individual tiles.
|
// Copy the tile16 data into individual tiles.
|
||||||
auto tile16_data = overworld_.tile16_blockset_data();
|
auto tile16_data = overworld_.tile16_blockset_data();
|
||||||
tile16_individual_.reserve(zelda3::kNumTile16Individual);
|
|
||||||
|
|
||||||
|
core::logf("Loading overworld tile16 graphics.");
|
||||||
// Loop through the tiles and copy their pixel data into separate vectors
|
// Loop through the tiles and copy their pixel data into separate vectors
|
||||||
for (uint i = 0; i < zelda3::kNumTile16Individual; i++) {
|
for (uint i = 0; i < zelda3::kNumTile16Individual; i++) {
|
||||||
std::vector<uint8_t> tile_data(kTile16Size * kTile16Size, 0x00);
|
tile16_individual_[i].Create(kTile16Size, kTile16Size, 0x08, kTile16Size * kTile16Size);
|
||||||
|
|
||||||
// Copy the pixel data for the current tile into the vector
|
// Copy the pixel data for the current tile into the vector
|
||||||
for (int ty = 0; ty < kTile16Size; ty++) {
|
for (int ty = 0; ty < kTile16Size; ty++) {
|
||||||
for (int tx = 0; tx < kTile16Size; tx++) {
|
for (int tx = 0; tx < kTile16Size; tx++) {
|
||||||
int position = tx + (ty * kTile16Size);
|
int position = tx + (ty * kTile16Size);
|
||||||
uint8_t value =
|
uint8_t value =
|
||||||
tile16_data[(i % 8 * kTile16Size) + (i / 8 * kTile16Size * 0x80) +
|
tile16_data[(i % 8 * kTile16Size) + (i / 8 * kTile16Size * 0x80) +
|
||||||
(ty * 0x80) + tx];
|
(ty * 0x80) + tx];
|
||||||
tile_data[position] = value;
|
tile16_individual_[i].mutable_data()[position] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the vector for the current tile to the vector of tile pixel data
|
RETURN_IF_ERROR(tile16_individual_[i].ApplyPalette(palette_));
|
||||||
tile16_individual_data_.push_back(tile_data);
|
Renderer::GetInstance().RenderBitmap(&tile16_individual_[i]);
|
||||||
tile16_individual_.emplace_back();
|
|
||||||
RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
|
|
||||||
kTile16Size, kTile16Size, 0x80, tile16_individual_data_[i],
|
|
||||||
tile16_individual_[i], palette_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core::logf("Loading overworld maps.");
|
||||||
// Render the overworld maps loaded from the ROM.
|
// Render the overworld maps loaded from the ROM.
|
||||||
for (int i = 0; i < zelda3::kNumOverworldMaps; ++i) {
|
for (int i = 0; i < zelda3::kNumOverworldMaps; ++i) {
|
||||||
overworld_.set_current_map(i);
|
overworld_.set_current_map(i);
|
||||||
auto palette = overworld_.current_area_palette();
|
auto palette = overworld_.current_area_palette();
|
||||||
RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
|
try {
|
||||||
kOverworldMapSize, kOverworldMapSize, 0x200,
|
RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
|
||||||
|
kOverworldMapSize, kOverworldMapSize, 0x80,
|
||||||
overworld_.current_map_bitmap_data(), maps_bmp_[i], palette));
|
overworld_.current_map_bitmap_data(), maps_bmp_[i], palette));
|
||||||
|
}
|
||||||
|
catch (const std::bad_alloc& e) {
|
||||||
|
std::cout << "Error: " << e.what() << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (core::ExperimentFlags::get().overworld.kDrawOverworldSprites) {
|
if (core::ExperimentFlags::get().overworld.kDrawOverworldSprites) {
|
||||||
@@ -1148,6 +1155,7 @@ void OverworldEditor::RefreshOverworldMap() {
|
|||||||
std::async(std::launch::async, refresh_map_async, source_map_id));
|
std::async(std::launch::async, refresh_map_async, source_map_id));
|
||||||
|
|
||||||
for (auto &each : futures) {
|
for (auto &each : futures) {
|
||||||
|
each.wait();
|
||||||
each.get();
|
each.get();
|
||||||
}
|
}
|
||||||
int n = is_large ? 4 : 1;
|
int n = is_large ? 4 : 1;
|
||||||
@@ -1215,12 +1223,12 @@ absl::Status OverworldEditor::RefreshTile16Blockset() {
|
|||||||
// Copy the tile16 data into individual tiles.
|
// Copy the tile16 data into individual tiles.
|
||||||
const auto tile16_data = overworld_.tile16_blockset_data();
|
const auto tile16_data = overworld_.tile16_blockset_data();
|
||||||
|
|
||||||
std::vector<std::future<void>> futures;
|
|
||||||
// Loop through the tiles and copy their pixel data into separate vectors
|
// Loop through the tiles and copy their pixel data into separate vectors
|
||||||
|
std::vector<std::future<absl::Status>> futures;
|
||||||
for (uint i = 0; i < zelda3::kNumTile16Individual; i++) {
|
for (uint i = 0; i < zelda3::kNumTile16Individual; i++) {
|
||||||
futures.push_back(std::async(
|
futures.push_back(std::async(
|
||||||
std::launch::async,
|
std::launch::async,
|
||||||
[&](int index) {
|
[&](int index) -> absl::Status {
|
||||||
std::vector<uint8_t> tile_data(16 * 16, 0x00);
|
std::vector<uint8_t> tile_data(16 * 16, 0x00);
|
||||||
for (int ty = 0; ty < 16; ty++) {
|
for (int ty = 0; ty < 16; ty++) {
|
||||||
for (int tx = 0; tx < 16; tx++) {
|
for (int tx = 0; tx < 16; tx++) {
|
||||||
@@ -1232,17 +1240,19 @@ absl::Status OverworldEditor::RefreshTile16Blockset() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tile16_individual_[index].set_data(tile_data);
|
tile16_individual_[index].set_data(tile_data);
|
||||||
|
RETURN_IF_ERROR(tile16_individual_[index].ApplyPalette(palette_));
|
||||||
|
return absl::OkStatus();
|
||||||
},
|
},
|
||||||
i));
|
i));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &future : futures) {
|
for (auto &future : futures) {
|
||||||
future.get();
|
future.wait();
|
||||||
|
RETURN_IF_ERROR(future.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the bitmaps of each tile.
|
// Render the bitmaps of each tile.
|
||||||
for (uint id = 0; id < zelda3::kNumTile16Individual; id++) {
|
for (uint id = 0; id < zelda3::kNumTile16Individual; id++) {
|
||||||
RETURN_IF_ERROR(tile16_individual_[id].ApplyPalette(palette_));
|
|
||||||
Renderer::GetInstance().UpdateBitmap(&tile16_individual_[id]);
|
Renderer::GetInstance().UpdateBitmap(&tile16_individual_[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -233,15 +233,14 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
|||||||
bool is_dragging_entity_ = false;
|
bool is_dragging_entity_ = false;
|
||||||
|
|
||||||
std::vector<uint8_t> selected_tile_data_;
|
std::vector<uint8_t> selected_tile_data_;
|
||||||
std::vector<std::vector<uint8_t>> tile16_individual_data_;
|
std::array<gfx::Bitmap, zelda3::kNumTile16Individual> tile16_individual_;
|
||||||
std::vector<gfx::Bitmap> tile16_individual_;
|
|
||||||
|
|
||||||
std::vector<std::vector<uint8_t>> tile8_individual_data_;
|
std::vector<std::vector<uint8_t>> tile8_individual_data_;
|
||||||
std::vector<gfx::Bitmap> tile8_individual_;
|
std::vector<gfx::Bitmap> tile8_individual_;
|
||||||
|
|
||||||
Rom& rom_;
|
Rom& rom_;
|
||||||
|
|
||||||
Tile16Editor tile16_editor_;
|
Tile16Editor tile16_editor_{ tile16_individual_ };
|
||||||
GfxGroupEditor gfx_group_editor_;
|
GfxGroupEditor gfx_group_editor_;
|
||||||
PaletteEditor palette_editor_;
|
PaletteEditor palette_editor_;
|
||||||
|
|
||||||
@@ -252,11 +251,11 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
|||||||
gfx::Bitmap current_gfx_bmp_;
|
gfx::Bitmap current_gfx_bmp_;
|
||||||
gfx::Bitmap all_gfx_bmp;
|
gfx::Bitmap all_gfx_bmp;
|
||||||
|
|
||||||
gfx::BitmapTable maps_bmp_;
|
std::array<gfx::Bitmap, zelda3::kNumOverworldMaps> maps_bmp_;
|
||||||
gfx::BitmapTable current_graphics_set_;
|
gfx::BitmapTable current_graphics_set_;
|
||||||
gfx::BitmapTable sprite_previews_;
|
gfx::BitmapTable sprite_previews_;
|
||||||
|
|
||||||
zelda3::Overworld overworld_;
|
zelda3::Overworld overworld_{rom_};
|
||||||
zelda3::OverworldBlockset refresh_blockset_;
|
zelda3::OverworldBlockset refresh_blockset_;
|
||||||
|
|
||||||
zelda3::Sprite current_sprite_;
|
zelda3::Sprite current_sprite_;
|
||||||
@@ -264,10 +263,10 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
|||||||
zelda3::OverworldEntrance current_entrance_;
|
zelda3::OverworldEntrance current_entrance_;
|
||||||
zelda3::OverworldExit current_exit_;
|
zelda3::OverworldExit current_exit_;
|
||||||
zelda3::OverworldItem current_item_;
|
zelda3::OverworldItem current_item_;
|
||||||
zelda3::OverworldEntranceTileTypes entrance_tiletypes_;
|
zelda3::OverworldEntranceTileTypes entrance_tiletypes_ = {};
|
||||||
|
|
||||||
zelda3::GameEntity* current_entity_;
|
zelda3::GameEntity* current_entity_ = nullptr;
|
||||||
zelda3::GameEntity* dragged_entity_;
|
zelda3::GameEntity* dragged_entity_ = nullptr;
|
||||||
|
|
||||||
gui::Canvas ow_map_canvas_{"OwMap", kOverworldCanvasSize,
|
gui::Canvas ow_map_canvas_{"OwMap", kOverworldCanvasSize,
|
||||||
gui::CanvasGridSize::k64x64};
|
gui::CanvasGridSize::k64x64};
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ void SpriteEditor::DrawCurrentSheets() {
|
|||||||
graphics_sheet_canvas_.DrawTileSelector(32);
|
graphics_sheet_canvas_.DrawTileSelector(32);
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
graphics_sheet_canvas_.DrawBitmap(
|
graphics_sheet_canvas_.DrawBitmap(
|
||||||
rom()->gfx_sheets().at(current_sheets_[i]), 1, (i * 0x40) + 1, 2);
|
GraphicsSheetManager::GetInstance().gfx_sheets().at(current_sheets_[i]), 1, (i * 0x40) + 1, 2);
|
||||||
}
|
}
|
||||||
graphics_sheet_canvas_.DrawGrid();
|
graphics_sheet_canvas_.DrawGrid();
|
||||||
graphics_sheet_canvas_.DrawOverlay();
|
graphics_sheet_canvas_.DrawOverlay();
|
||||||
|
|||||||
@@ -15,45 +15,42 @@ using ImGui::MenuItem;
|
|||||||
using ImGui::Separator;
|
using ImGui::Separator;
|
||||||
|
|
||||||
struct FlagsMenu {
|
struct FlagsMenu {
|
||||||
void Draw() {
|
void DrawOverworldFlags() {
|
||||||
if (BeginMenu("Overworld Flags")) {
|
Checkbox("Enable Overworld Sprites",
|
||||||
Checkbox("Enable Overworld Sprites",
|
&ExperimentFlags::get().overworld.kDrawOverworldSprites);
|
||||||
&ExperimentFlags::get().overworld.kDrawOverworldSprites);
|
Separator();
|
||||||
Separator();
|
Checkbox("Save Overworld Maps",
|
||||||
Checkbox("Save Overworld Maps",
|
&ExperimentFlags::get().overworld.kSaveOverworldMaps);
|
||||||
&ExperimentFlags::get().overworld.kSaveOverworldMaps);
|
Checkbox("Save Overworld Entrances",
|
||||||
Checkbox("Save Overworld Entrances",
|
&ExperimentFlags::get().overworld.kSaveOverworldEntrances);
|
||||||
&ExperimentFlags::get().overworld.kSaveOverworldEntrances);
|
Checkbox("Save Overworld Exits",
|
||||||
Checkbox("Save Overworld Exits",
|
&ExperimentFlags::get().overworld.kSaveOverworldExits);
|
||||||
&ExperimentFlags::get().overworld.kSaveOverworldExits);
|
Checkbox("Save Overworld Items",
|
||||||
Checkbox("Save Overworld Items",
|
&ExperimentFlags::get().overworld.kSaveOverworldItems);
|
||||||
&ExperimentFlags::get().overworld.kSaveOverworldItems);
|
Checkbox("Save Overworld Properties",
|
||||||
Checkbox("Save Overworld Properties",
|
&ExperimentFlags::get().overworld.kSaveOverworldProperties);
|
||||||
&ExperimentFlags::get().overworld.kSaveOverworldProperties);
|
Checkbox("Load Custom Overworld",
|
||||||
Checkbox("Load Custom Overworld",
|
&ExperimentFlags::get().overworld.kLoadCustomOverworld);
|
||||||
&ExperimentFlags::get().overworld.kLoadCustomOverworld);
|
}
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BeginMenu("Dungeon Flags")) {
|
void DrawDungeonFlags() {
|
||||||
Checkbox("Draw Dungeon Room Graphics",
|
Checkbox("Draw Dungeon Room Graphics",
|
||||||
&ExperimentFlags::get().kDrawDungeonRoomGraphics);
|
&ExperimentFlags::get().kDrawDungeonRoomGraphics);
|
||||||
Separator();
|
Separator();
|
||||||
Checkbox("Save Dungeon Maps", &ExperimentFlags::get().kSaveDungeonMaps);
|
Checkbox("Save Dungeon Maps", &ExperimentFlags::get().kSaveDungeonMaps);
|
||||||
ImGui::EndMenu();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Checkbox("Use built-in file dialog",
|
void DrawResourceFlags() {
|
||||||
&ExperimentFlags::get().kNewFileDialogWrapper);
|
|
||||||
Checkbox("Enable Console Logging", &ExperimentFlags::get().kLogToConsole);
|
|
||||||
Checkbox("Enable Texture Streaming",
|
|
||||||
&ExperimentFlags::get().kLoadTexturesAsStreaming);
|
|
||||||
Checkbox("Log Instructions to Debugger",
|
|
||||||
&ExperimentFlags::get().kLogInstructions);
|
|
||||||
Checkbox("Save All Palettes", &ExperimentFlags::get().kSaveAllPalettes);
|
Checkbox("Save All Palettes", &ExperimentFlags::get().kSaveAllPalettes);
|
||||||
Checkbox("Save Gfx Groups", &ExperimentFlags::get().kSaveGfxGroups);
|
Checkbox("Save Gfx Groups", &ExperimentFlags::get().kSaveGfxGroups);
|
||||||
Checkbox("Save Graphics Sheets",
|
Checkbox("Save Graphics Sheets",
|
||||||
&ExperimentFlags::get().kSaveGraphicsSheet);
|
&ExperimentFlags::get().kSaveGraphicsSheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawSystemFlags() {
|
||||||
|
Checkbox("Enable Console Logging", &ExperimentFlags::get().kLogToConsole);
|
||||||
|
Checkbox("Log Instructions to Emulator Debugger",
|
||||||
|
&ExperimentFlags::get().kLogInstructions);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#include "app/editor/system/settings_editor.h"
|
#include "app/editor/system/settings_editor.h"
|
||||||
|
|
||||||
|
#include "app/gui/style.h"
|
||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "app/editor/system/flags.h"
|
#include "app/editor/system/flags.h"
|
||||||
#include "imgui/imgui.h"
|
#include "imgui/imgui.h"
|
||||||
@@ -34,6 +35,10 @@ absl::Status SettingsEditor::Update() {
|
|||||||
DrawGeneralSettings();
|
DrawGeneralSettings();
|
||||||
EndTabItem();
|
EndTabItem();
|
||||||
}
|
}
|
||||||
|
if (BeginTabItem("Font Manager")) {
|
||||||
|
gui::DrawFontManager();
|
||||||
|
EndTabItem();
|
||||||
|
}
|
||||||
if (BeginTabItem("Keyboard Shortcuts")) {
|
if (BeginTabItem("Keyboard Shortcuts")) {
|
||||||
EndTabItem();
|
EndTabItem();
|
||||||
}
|
}
|
||||||
@@ -44,28 +49,44 @@ absl::Status SettingsEditor::Update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SettingsEditor::DrawGeneralSettings() {
|
void SettingsEditor::DrawGeneralSettings() {
|
||||||
if (BeginTable("##SettingsTable", 2,
|
static FlagsMenu flags;
|
||||||
|
|
||||||
|
if (BeginTable("##SettingsTable", 4,
|
||||||
ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable |
|
ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable |
|
||||||
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable)) {
|
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable)) {
|
||||||
TableSetupColumn("Experiment Flags", ImGuiTableColumnFlags_WidthFixed,
|
TableSetupColumn("System Flags", ImGuiTableColumnFlags_WidthStretch);
|
||||||
250.0f);
|
TableSetupColumn("Overworld Flags", ImGuiTableColumnFlags_WidthStretch);
|
||||||
TableSetupColumn("General Setting", ImGuiTableColumnFlags_WidthStretch,
|
TableSetupColumn("Dungeon Flags", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
TableSetupColumn("Resource Flags", ImGuiTableColumnFlags_WidthStretch,
|
||||||
0.0f);
|
0.0f);
|
||||||
|
|
||||||
TableHeadersRow();
|
TableHeadersRow();
|
||||||
|
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
if (BeginChild("##GeneralSettingsStyleWrapper", ImVec2(0, 0),
|
if (BeginChild("##SystemFlags", ImVec2(0, 0),
|
||||||
ImGuiChildFlags_FrameStyle)) {
|
ImGuiChildFlags_FrameStyle)) {
|
||||||
static FlagsMenu flags;
|
flags.DrawSystemFlags();
|
||||||
flags.Draw();
|
|
||||||
EndChild();
|
EndChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
if (BeginChild("##GeneralSettingsWrapper", ImVec2(0, 0),
|
if (BeginChild("##OverworldFlags", ImVec2(0, 0),
|
||||||
ImGuiChildFlags_FrameStyle)) {
|
ImGuiChildFlags_FrameStyle)) {
|
||||||
Text("TODO: Add some settings here");
|
flags.DrawOverworldFlags();
|
||||||
|
EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
TableNextColumn();
|
||||||
|
if (BeginChild("##DungeonFlags", ImVec2(0, 0),
|
||||||
|
ImGuiChildFlags_FrameStyle)) {
|
||||||
|
flags.DrawDungeonFlags();
|
||||||
|
EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
TableNextColumn();
|
||||||
|
if (BeginChild("##ResourceFlags", ImVec2(0, 0),
|
||||||
|
ImGuiChildFlags_FrameStyle)) {
|
||||||
|
flags.DrawResourceFlags();
|
||||||
EndChild();
|
EndChild();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -218,6 +218,13 @@ Bitmap::Bitmap(int width, int height, int depth, int data_size) {
|
|||||||
Create(width, height, depth, std::vector<uint8_t>(data_size, 0));
|
Create(width, height, depth, std::vector<uint8_t>(data_size, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bitmap::Initialize(int width, int height, int depth, std::span<uint8_t>& data) {
|
||||||
|
width_ = width;
|
||||||
|
height_ = height;
|
||||||
|
depth_ = depth;
|
||||||
|
data_ = std::vector<uint8_t>(data.begin(), data.end());
|
||||||
|
}
|
||||||
|
|
||||||
void Bitmap::Create(int width, int height, int depth, std::span<uint8_t> data) {
|
void Bitmap::Create(int width, int height, int depth, std::span<uint8_t> data) {
|
||||||
data_ = std::vector<uint8_t>(data.begin(), data.end());
|
data_ = std::vector<uint8_t>(data.begin(), data.end());
|
||||||
Create(width, height, depth, data_);
|
Create(width, height, depth, data_);
|
||||||
@@ -239,19 +246,20 @@ void Bitmap::Create(int width, int height, int depth, int format,
|
|||||||
width_ = width;
|
width_ = width;
|
||||||
height_ = height;
|
height_ = height;
|
||||||
depth_ = depth;
|
depth_ = depth;
|
||||||
data_ = data;
|
|
||||||
data_size_ = data.size();
|
data_size_ = data.size();
|
||||||
if (data_size_ == 0) {
|
if (data_size_ == 0) {
|
||||||
SDL_Log("Data provided to Bitmap is empty.\n");
|
SDL_Log("Data provided to Bitmap is empty.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
data_.reserve(data_size_);
|
||||||
|
data_ = data;
|
||||||
pixel_data_ = data_.data();
|
pixel_data_ = data_.data();
|
||||||
surface_ = std::shared_ptr<SDL_Surface>{
|
surface_ = std::shared_ptr<SDL_Surface>{
|
||||||
SDL_CreateRGBSurfaceWithFormat(0, width_, height_, depth_,
|
SDL_CreateRGBSurfaceWithFormat(0, width_, height_, depth_,
|
||||||
GetSnesPixelFormat(format)),
|
GetSnesPixelFormat(format)),
|
||||||
SDL_Surface_Deleter{}};
|
SDL_Surface_Deleter{}};
|
||||||
if (surface_ == nullptr) {
|
if (surface_ == nullptr) {
|
||||||
SDL_Log("SDL_CreateRGBSurfaceWithFormat failed: %s\n", SDL_GetError());
|
SDL_Log("Bitmap::Create.SDL_CreateRGBSurfaceWithFormat failed: %s\n", SDL_GetError());
|
||||||
active_ = false;
|
active_ = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -285,14 +293,15 @@ void Bitmap::CreateTexture(SDL_Renderer *renderer) {
|
|||||||
SDL_TEXTUREACCESS_STREAMING, width_, height_),
|
SDL_TEXTUREACCESS_STREAMING, width_, height_),
|
||||||
SDL_Texture_Deleter{}};
|
SDL_Texture_Deleter{}};
|
||||||
if (texture_ == nullptr) {
|
if (texture_ == nullptr) {
|
||||||
SDL_Log("SDL_CreateTextureFromSurface failed: %s\n", SDL_GetError());
|
SDL_Log("Bitmap::CreateTexture.SDL_CreateTextureFromSurface failed: %s\n", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
texture_pixels = data_.data();
|
||||||
|
|
||||||
auto converted_surface_ = std::shared_ptr<SDL_Surface>{
|
auto converted_surface_ = std::shared_ptr<SDL_Surface>{
|
||||||
SDL_ConvertSurfaceFormat(surface_.get(), SDL_PIXELFORMAT_ARGB8888, 0),
|
SDL_ConvertSurfaceFormat(surface_.get(), SDL_PIXELFORMAT_ARGB8888, 0),
|
||||||
SDL_Surface_Deleter{}};
|
SDL_Surface_Deleter{}};
|
||||||
if (converted_surface_ == nullptr) {
|
if (converted_surface_ == nullptr) {
|
||||||
SDL_Log("SDL_ConvertSurfaceFormat failed: %s\n", SDL_GetError());
|
SDL_Log("Bitmap::CreateTexture.SDL_ConvertSurfaceFormat failed: %s\n", SDL_GetError());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ enum BitmapFormat {
|
|||||||
/**
|
/**
|
||||||
* @brief Convert SDL_Surface to PNG image data.
|
* @brief Convert SDL_Surface to PNG image data.
|
||||||
*/
|
*/
|
||||||
bool ConvertSurfaceToPNG(SDL_Surface *surface, std::vector<uint8_t> &buffer);
|
bool ConvertSurfaceToPng(SDL_Surface *surface, std::vector<uint8_t> &buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert PNG image data to SDL_Surface.
|
* @brief Convert PNG image data to SDL_Surface.
|
||||||
@@ -91,9 +91,11 @@ class Bitmap {
|
|||||||
|
|
||||||
void SaveSurfaceToFile(std::string_view filename);
|
void SaveSurfaceToFile(std::string_view filename);
|
||||||
|
|
||||||
/**
|
void Initialize(int width, int height, int depth, std::span<uint8_t>& data);
|
||||||
* @brief Creates a bitmap object with the provided graphical data.
|
|
||||||
*/
|
void Create(int width, int height, int depth, int data_size) {
|
||||||
|
Create(width, height, depth, std::vector<uint8_t>(data_size, 0));
|
||||||
|
}
|
||||||
void Create(int width, int height, int depth, std::span<uint8_t> data);
|
void Create(int width, int height, int depth, std::span<uint8_t> data);
|
||||||
void Create(int width, int height, int depth,
|
void Create(int width, int height, int depth,
|
||||||
const std::vector<uint8_t> &data);
|
const std::vector<uint8_t> &data);
|
||||||
@@ -152,7 +154,6 @@ class Bitmap {
|
|||||||
|
|
||||||
auto palette() const { return palette_; }
|
auto palette() const { return palette_; }
|
||||||
auto mutable_palette() { return &palette_; }
|
auto mutable_palette() { return &palette_; }
|
||||||
auto palette_size() const { return palette_.size(); }
|
|
||||||
|
|
||||||
int width() const { return width_; }
|
int width() const { return width_; }
|
||||||
int height() const { return height_; }
|
int height() const { return height_; }
|
||||||
@@ -161,7 +162,6 @@ class Bitmap {
|
|||||||
auto data() const { return data_.data(); }
|
auto data() const { return data_.data(); }
|
||||||
auto &mutable_data() { return data_; }
|
auto &mutable_data() { return data_; }
|
||||||
auto surface() const { return surface_.get(); }
|
auto surface() const { return surface_.get(); }
|
||||||
auto mutable_surface() { return surface_.get(); }
|
|
||||||
|
|
||||||
auto vector() const { return data_; }
|
auto vector() const { return data_; }
|
||||||
auto at(int i) const { return data_[i]; }
|
auto at(int i) const { return data_[i]; }
|
||||||
|
|||||||
@@ -533,7 +533,7 @@ void Canvas::DrawOutlineWithColor(int x, int y, int w, int h, uint32_t color) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawBitmapGroup(std::vector<int> &group,
|
void Canvas::DrawBitmapGroup(std::vector<int> &group,
|
||||||
std::vector<gfx::Bitmap> &tile16_individual_,
|
std::array<gfx::Bitmap, 4096> &tile16_individual_,
|
||||||
int tile_size, float scale) {
|
int tile_size, float scale) {
|
||||||
if (selected_points_.size() != 2) {
|
if (selected_points_.size() != 2) {
|
||||||
// points_ should contain exactly two points
|
// points_ should contain exactly two points
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef YAZE_GUI_CANVAS_H
|
#ifndef YAZE_GUI_CANVAS_H
|
||||||
#define YAZE_GUI_CANVAS_H
|
#define YAZE_GUI_CANVAS_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
@@ -110,7 +111,7 @@ public:
|
|||||||
void DrawBitmapTable(const BitmapTable &gfx_bin);
|
void DrawBitmapTable(const BitmapTable &gfx_bin);
|
||||||
|
|
||||||
void DrawBitmapGroup(std::vector<int> &group,
|
void DrawBitmapGroup(std::vector<int> &group,
|
||||||
std::vector<gfx::Bitmap> &tile16_individual_,
|
std::array<gfx::Bitmap, 4096>& tile16_individual_,
|
||||||
int tile_size, float scale = 1.0f);
|
int tile_size, float scale = 1.0f);
|
||||||
|
|
||||||
void DrawOutline(int x, int y, int w, int h);
|
void DrawOutline(int x, int y, int w, int h);
|
||||||
@@ -130,8 +131,8 @@ public:
|
|||||||
void DrawLayeredElements();
|
void DrawLayeredElements();
|
||||||
|
|
||||||
int GetTileIdFromMousePos() {
|
int GetTileIdFromMousePos() {
|
||||||
int x = mouse_pos_in_canvas_.x;
|
float x = mouse_pos_in_canvas_.x;
|
||||||
int y = mouse_pos_in_canvas_.y;
|
float y = mouse_pos_in_canvas_.y;
|
||||||
int num_columns = (canvas_sz_.x / global_scale_) / custom_step_;
|
int num_columns = (canvas_sz_.x / global_scale_) / custom_step_;
|
||||||
int num_rows = (canvas_sz_.y / global_scale_) / custom_step_;
|
int num_rows = (canvas_sz_.y / global_scale_) / custom_step_;
|
||||||
int tile_id = (x / custom_step_) + (y / custom_step_) * num_columns;
|
int tile_id = (x / custom_step_) + (y / custom_step_) * num_columns;
|
||||||
@@ -206,6 +207,7 @@ private:
|
|||||||
bool enable_context_menu_ = true;
|
bool enable_context_menu_ = true;
|
||||||
bool custom_canvas_size_ = false;
|
bool custom_canvas_size_ = false;
|
||||||
bool select_rect_active_ = false;
|
bool select_rect_active_ = false;
|
||||||
|
bool refresh_graphics_ = false;
|
||||||
|
|
||||||
float custom_step_ = 0.0f;
|
float custom_step_ = 0.0f;
|
||||||
float global_scale_ = 1.0f;
|
float global_scale_ = 1.0f;
|
||||||
@@ -216,14 +218,9 @@ private:
|
|||||||
uint16_t edit_palette_index_ = 0;
|
uint16_t edit_palette_index_ = 0;
|
||||||
uint64_t edit_palette_group_name_index_ = 0;
|
uint64_t edit_palette_group_name_index_ = 0;
|
||||||
uint64_t edit_palette_sub_index_ = 0;
|
uint64_t edit_palette_sub_index_ = 0;
|
||||||
bool refresh_graphics_ = false;
|
|
||||||
|
|
||||||
std::string canvas_id_ = "Canvas";
|
ImDrawList* draw_list_ = nullptr;
|
||||||
std::string context_id_ = "CanvasContext";
|
|
||||||
|
|
||||||
ImDrawList *draw_list_;
|
|
||||||
ImVector<ImVec2> points_;
|
|
||||||
ImVector<ImVector<std::string>> labels_;
|
|
||||||
ImVec2 scrolling_;
|
ImVec2 scrolling_;
|
||||||
ImVec2 canvas_sz_;
|
ImVec2 canvas_sz_;
|
||||||
ImVec2 canvas_p0_;
|
ImVec2 canvas_p0_;
|
||||||
@@ -231,7 +228,13 @@ private:
|
|||||||
ImVec2 drawn_tile_pos_;
|
ImVec2 drawn_tile_pos_;
|
||||||
ImVec2 mouse_pos_in_canvas_;
|
ImVec2 mouse_pos_in_canvas_;
|
||||||
ImVec2 selected_tile_pos_ = ImVec2(-1, -1);
|
ImVec2 selected_tile_pos_ = ImVec2(-1, -1);
|
||||||
|
|
||||||
|
ImVector<ImVec2> points_;
|
||||||
ImVector<ImVec2> selected_points_;
|
ImVector<ImVec2> selected_points_;
|
||||||
|
ImVector<ImVector<std::string>> labels_;
|
||||||
|
|
||||||
|
std::string canvas_id_ = "Canvas";
|
||||||
|
std::string context_id_ = "CanvasContext";
|
||||||
std::vector<ImVec2> selected_tiles_;
|
std::vector<ImVec2> selected_tiles_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// for use with https://github.com/google/material-design-icons/blob/master/font/MaterialIcons-Regular.ttf
|
// for use with https://github.com/google/material-design-icons/blob/master/font/MaterialIcons-Regular.ttf
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define FONT_ICON_FILE_NAME_MD "assets/font/MaterialIcons-Regular.ttf"
|
#define FONT_ICON_FILE_NAME_MD "MaterialIcons-Regular.ttf"
|
||||||
|
|
||||||
#define ICON_MIN_MD 0xe000
|
#define ICON_MIN_MD 0xe000
|
||||||
#define ICON_MAX_MD 0x10fffd
|
#define ICON_MAX_MD 0x10fffd
|
||||||
|
|||||||
@@ -749,5 +749,34 @@ void TextWithSeparators(const absl::string_view &text) {
|
|||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawFontManager() {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImFontAtlas* atlas = io.Fonts;
|
||||||
|
static ImFont* current_font = atlas->Fonts[0];
|
||||||
|
static int current_font_index = 0;
|
||||||
|
static int font_size = 16;
|
||||||
|
static bool font_selected = false;
|
||||||
|
ImGui::Text("Current Font: %s", current_font->GetDebugName());
|
||||||
|
ImGui::Text("Font Size: %d", font_size);
|
||||||
|
if (ImGui::BeginCombo("Fonts", current_font->GetDebugName())) {
|
||||||
|
for (int i = 0; i < atlas->Fonts.Size; i++) {
|
||||||
|
bool is_selected = (current_font == atlas->Fonts[i]);
|
||||||
|
if (ImGui::Selectable(atlas->Fonts[i]->GetDebugName(), is_selected)) {
|
||||||
|
current_font = atlas->Fonts[i];
|
||||||
|
current_font_index = i;
|
||||||
|
font_selected = true;
|
||||||
|
}
|
||||||
|
if (is_selected) {
|
||||||
|
ImGui::SetItemDefaultFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
if (ImGui::SliderInt("Font Size", &font_size, 8, 32)) {
|
||||||
|
current_font->Scale = font_size / 16.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ void DrawDisplaySettings(ImGuiStyle *ref = nullptr);
|
|||||||
|
|
||||||
void TextWithSeparators(const absl::string_view &text);
|
void TextWithSeparators(const absl::string_view &text);
|
||||||
|
|
||||||
|
void DrawFontManager();
|
||||||
|
|
||||||
static const char *ExampleNames[] = {
|
static const char *ExampleNames[] = {
|
||||||
"Artichoke", "Arugula", "Asparagus", "Avocado",
|
"Artichoke", "Arugula", "Asparagus", "Avocado",
|
||||||
"Bamboo Shoots", "Bean Sprouts", "Beans", "Beet",
|
"Bamboo Shoots", "Bean Sprouts", "Beans", "Beet",
|
||||||
|
|||||||
105
src/app/rom.cc
105
src/app/rom.cc
@@ -1,5 +1,6 @@
|
|||||||
#include "rom.h"
|
#include "rom.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@@ -53,26 +54,27 @@ absl::StatusOr<std::vector<uint8_t>> Load2BppGraphics(const Rom &rom) {
|
|||||||
return sheet;
|
return sheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Rom::LoadLinkGraphics() {
|
absl::StatusOr<std::array<gfx::Bitmap, kNumLinkSheets>> LoadLinkGraphics(const Rom& rom) {
|
||||||
const uint32_t kLinkGfxOffset = 0x80000; // $10:8000
|
const uint32_t kLinkGfxOffset = 0x80000; // $10:8000
|
||||||
const uint16_t kLinkGfxLength = 0x800; // 0x4000 or 0x7000?
|
const uint16_t kLinkGfxLength = 0x800; // 0x4000 or 0x7000?
|
||||||
|
std::array<gfx::Bitmap, kNumLinkSheets> link_graphics;
|
||||||
// Load Links graphics from the ROM
|
|
||||||
for (uint32_t i = 0; i < kNumLinkSheets; i++) {
|
for (uint32_t i = 0; i < kNumLinkSheets; i++) {
|
||||||
ASSIGN_OR_RETURN(
|
ASSIGN_OR_RETURN(
|
||||||
auto link_sheet_data,
|
auto link_sheet_data,
|
||||||
ReadByteVector(/*offset=*/kLinkGfxOffset + (i * kLinkGfxLength),
|
rom.ReadByteVector(/*offset=*/kLinkGfxOffset + (i * kLinkGfxLength),
|
||||||
/*length=*/kLinkGfxLength))
|
/*length=*/kLinkGfxLength))
|
||||||
auto link_sheet_8bpp = gfx::SnesTo8bppSheet(link_sheet_data, /*bpp=*/4);
|
auto link_sheet_8bpp = gfx::SnesTo8bppSheet(link_sheet_data, /*bpp=*/4);
|
||||||
link_graphics_[i].Create(gfx::kTilesheetWidth, gfx::kTilesheetHeight,
|
link_graphics[i].Create(gfx::kTilesheetWidth, gfx::kTilesheetHeight,
|
||||||
gfx::kTilesheetDepth, link_sheet_8bpp);
|
gfx::kTilesheetDepth, link_sheet_8bpp);
|
||||||
RETURN_IF_ERROR(link_graphics_[i].ApplyPalette(palette_groups_.armors[0]);)
|
RETURN_IF_ERROR(link_graphics[i].ApplyPalette(rom.palette_group().armors[0]);)
|
||||||
Renderer::GetInstance().RenderBitmap(&link_graphics_[i]);
|
Renderer::GetInstance().RenderBitmap(&link_graphics[i]);
|
||||||
}
|
}
|
||||||
return absl::OkStatus();
|
return link_graphics;
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Rom::LoadAllGraphicsData(bool defer_render) {
|
absl::StatusOr<std::array<gfx::Bitmap, kNumGfxSheets>>
|
||||||
|
LoadAllGraphicsData(Rom& rom, bool defer_render) {
|
||||||
|
std::array<gfx::Bitmap, kNumGfxSheets> graphics_sheets;
|
||||||
std::vector<uint8_t> sheet;
|
std::vector<uint8_t> sheet;
|
||||||
bool bpp3 = false;
|
bool bpp3 = false;
|
||||||
|
|
||||||
@@ -80,60 +82,60 @@ absl::Status Rom::LoadAllGraphicsData(bool defer_render) {
|
|||||||
if (i >= 115 && i <= 126) { // uncompressed sheets
|
if (i >= 115 && i <= 126) { // uncompressed sheets
|
||||||
sheet.resize(Uncompressed3BPPSize);
|
sheet.resize(Uncompressed3BPPSize);
|
||||||
auto offset =
|
auto offset =
|
||||||
GetGraphicsAddress(data(), i, version_constants().kOverworldGfxPtr1,
|
GetGraphicsAddress(rom.data(), i, rom.version_constants().kOverworldGfxPtr1,
|
||||||
version_constants().kOverworldGfxPtr2,
|
rom.version_constants().kOverworldGfxPtr2,
|
||||||
version_constants().kOverworldGfxPtr3);
|
rom.version_constants().kOverworldGfxPtr3);
|
||||||
for (int j = 0; j < Uncompressed3BPPSize; j++) {
|
std::copy(rom.data() + offset, rom.data() + offset + Uncompressed3BPPSize,
|
||||||
sheet[j] = rom_data_[j + offset];
|
sheet.begin());
|
||||||
}
|
|
||||||
bpp3 = true;
|
bpp3 = true;
|
||||||
} else if (i == 113 || i == 114 || i >= 218) {
|
} else if (i == 113 || i == 114 || i >= 218) {
|
||||||
bpp3 = false;
|
bpp3 = false;
|
||||||
} else {
|
} else {
|
||||||
auto offset =
|
auto offset =
|
||||||
GetGraphicsAddress(data(), i, version_constants().kOverworldGfxPtr1,
|
GetGraphicsAddress(rom.data(), i, rom.version_constants().kOverworldGfxPtr1,
|
||||||
version_constants().kOverworldGfxPtr2,
|
rom.version_constants().kOverworldGfxPtr2,
|
||||||
version_constants().kOverworldGfxPtr3);
|
rom.version_constants().kOverworldGfxPtr3);
|
||||||
ASSIGN_OR_RETURN(sheet,
|
ASSIGN_OR_RETURN(sheet,
|
||||||
gfx::lc_lz2::DecompressV2(rom_data_.data(), offset))
|
gfx::lc_lz2::DecompressV2(rom.data(), offset))
|
||||||
bpp3 = true;
|
bpp3 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bpp3) {
|
if (bpp3) {
|
||||||
auto converted_sheet = gfx::SnesTo8bppSheet(sheet, 3);
|
auto converted_sheet = gfx::SnesTo8bppSheet(sheet, 3);
|
||||||
graphics_sheets_[i].Create(gfx::kTilesheetWidth, gfx::kTilesheetHeight,
|
graphics_sheets[i].Create(gfx::kTilesheetWidth, gfx::kTilesheetHeight,
|
||||||
gfx::kTilesheetDepth, converted_sheet);
|
gfx::kTilesheetDepth, converted_sheet);
|
||||||
if (graphics_sheets_[i].is_active()) {
|
if (graphics_sheets[i].is_active()) {
|
||||||
if (i > 115) {
|
if (i > 115) {
|
||||||
// Apply sprites palette
|
// Apply sprites palette
|
||||||
RETURN_IF_ERROR(graphics_sheets_[i].ApplyPaletteWithTransparent(
|
RETURN_IF_ERROR(graphics_sheets[i].ApplyPaletteWithTransparent(
|
||||||
palette_groups_.global_sprites[0], 0));
|
rom.palette_group().global_sprites[0], 0));
|
||||||
} else {
|
} else {
|
||||||
RETURN_IF_ERROR(graphics_sheets_[i].ApplyPaletteWithTransparent(
|
RETURN_IF_ERROR(graphics_sheets[i].ApplyPaletteWithTransparent(
|
||||||
palette_groups_.dungeon_main[0], 0));
|
rom.palette_group().dungeon_main[0], 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!defer_render) {
|
if (!defer_render) {
|
||||||
graphics_sheets_[i].CreateTexture(Renderer::GetInstance().renderer());
|
graphics_sheets[i].CreateTexture(Renderer::GetInstance().renderer());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < graphics_sheets_[i].size(); ++j) {
|
for (int j = 0; j < graphics_sheets[i].size(); ++j) {
|
||||||
graphics_buffer_.push_back(graphics_sheets_[i].at(j));
|
rom.mutable_graphics_buffer()->push_back(graphics_sheets[i].at(j));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for (int j = 0; j < graphics_sheets_[0].size(); ++j) {
|
for (int j = 0; j < graphics_sheets[0].size(); ++j) {
|
||||||
graphics_buffer_.push_back(0xFF);
|
rom.mutable_graphics_buffer()->push_back(0xFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return absl::OkStatus();
|
return graphics_sheets;
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Rom::SaveAllGraphicsData() {
|
absl::Status
|
||||||
|
SaveAllGraphicsData(Rom& rom, std::array<gfx::Bitmap, kNumGfxSheets>& gfx_sheets) {
|
||||||
for (int i = 0; i < kNumGfxSheets; i++) {
|
for (int i = 0; i < kNumGfxSheets; i++) {
|
||||||
if (graphics_sheets_[i].is_active()) {
|
if (gfx_sheets[i].is_active()) {
|
||||||
int to_bpp = 3;
|
int to_bpp = 3;
|
||||||
std::vector<uint8_t> final_data;
|
std::vector<uint8_t> final_data;
|
||||||
bool compressed = true;
|
bool compressed = true;
|
||||||
@@ -145,7 +147,7 @@ absl::Status Rom::SaveAllGraphicsData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Sheet ID " << i << " BPP: " << to_bpp << std::endl;
|
std::cout << "Sheet ID " << i << " BPP: " << to_bpp << std::endl;
|
||||||
auto sheet_data = graphics_sheets_[i].vector();
|
auto sheet_data = gfx_sheets[i].vector();
|
||||||
std::cout << "Sheet data size: " << sheet_data.size() << std::endl;
|
std::cout << "Sheet data size: " << sheet_data.size() << std::endl;
|
||||||
final_data = gfx::Bpp8SnesToIndexed(sheet_data, 8);
|
final_data = gfx::Bpp8SnesToIndexed(sheet_data, 8);
|
||||||
int size = 0;
|
int size = 0;
|
||||||
@@ -157,11 +159,10 @@ absl::Status Rom::SaveAllGraphicsData() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto offset =
|
auto offset =
|
||||||
GetGraphicsAddress(data(), i, version_constants().kOverworldGfxPtr1,
|
GetGraphicsAddress(rom.data(), i, rom.version_constants().kOverworldGfxPtr1,
|
||||||
version_constants().kOverworldGfxPtr2,
|
rom.version_constants().kOverworldGfxPtr2,
|
||||||
version_constants().kOverworldGfxPtr3);
|
rom.version_constants().kOverworldGfxPtr3);
|
||||||
std::copy(final_data.begin(), final_data.end(),
|
std::copy(final_data.begin(), final_data.end(), rom.begin() + offset);
|
||||||
rom_data_.begin() + offset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
@@ -230,6 +231,17 @@ absl::Status Rom::LoadFromPointer(uchar *data, size_t length, bool z3_load) {
|
|||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
absl::Status Rom::LoadFromBytes(const std::vector<uint8_t>& data) {
|
||||||
|
if (data.empty()) {
|
||||||
|
return absl::InvalidArgumentError(
|
||||||
|
"Could not load ROM: parameter `data` is empty.");
|
||||||
|
}
|
||||||
|
rom_data_ = data;
|
||||||
|
size_ = data.size();
|
||||||
|
is_loaded_ = true;
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
absl::Status Rom::LoadZelda3() {
|
absl::Status Rom::LoadZelda3() {
|
||||||
// Check if the ROM has a header
|
// Check if the ROM has a header
|
||||||
constexpr size_t kBaseRomSize = 1048576; // 1MB
|
constexpr size_t kBaseRomSize = 1048576; // 1MB
|
||||||
@@ -266,17 +278,6 @@ absl::Status Rom::LoadZelda3() {
|
|||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Rom::LoadFromBytes(const std::vector<uint8_t> &data) {
|
|
||||||
if (data.empty()) {
|
|
||||||
return absl::InvalidArgumentError(
|
|
||||||
"Could not load ROM: parameter `data` is empty.");
|
|
||||||
}
|
|
||||||
rom_data_ = data;
|
|
||||||
size_ = data.size();
|
|
||||||
is_loaded_ = true;
|
|
||||||
return absl::OkStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Status Rom::SaveToFile(bool backup, bool save_new, std::string filename) {
|
absl::Status Rom::SaveToFile(bool backup, bool save_new, std::string filename) {
|
||||||
absl::Status non_firing_status;
|
absl::Status non_firing_status;
|
||||||
if (rom_data_.empty()) {
|
if (rom_data_.empty()) {
|
||||||
@@ -319,8 +320,6 @@ absl::Status Rom::SaveToFile(bool backup, bool save_new, std::string filename) {
|
|||||||
RETURN_IF_ERROR(SaveAllPalettes());
|
RETURN_IF_ERROR(SaveAllPalettes());
|
||||||
if (core::ExperimentFlags::get().kSaveGfxGroups)
|
if (core::ExperimentFlags::get().kSaveGfxGroups)
|
||||||
RETURN_IF_ERROR(SaveGroupsToRom());
|
RETURN_IF_ERROR(SaveGroupsToRom());
|
||||||
if (core::ExperimentFlags::get().kSaveGraphicsSheet)
|
|
||||||
RETURN_IF_ERROR(SaveAllGraphicsData());
|
|
||||||
|
|
||||||
if (save_new) {
|
if (save_new) {
|
||||||
// Create a file of the same name and append the date between the filename
|
// Create a file of the same name and append the date between the filename
|
||||||
|
|||||||
151
src/app/rom.h
151
src/app/rom.h
@@ -27,6 +27,24 @@
|
|||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
|
|
||||||
|
constexpr uint32_t kNumGfxSheets = 223;
|
||||||
|
constexpr uint32_t kNumLinkSheets = 14;
|
||||||
|
constexpr uint32_t kTile16Ptr = 0x78000;
|
||||||
|
constexpr uint32_t kNormalGfxSpaceStart = 0x87000;
|
||||||
|
constexpr uint32_t kNormalGfxSpaceEnd = 0xC4200;
|
||||||
|
constexpr uint32_t kFontSpriteLocation = 0x70000;
|
||||||
|
constexpr uint32_t kGfxGroupsPointer = 0x6237;
|
||||||
|
constexpr uint32_t kUncompressedSheetSize = 0x0800;
|
||||||
|
constexpr uint32_t kNumMainBlocksets = 37;
|
||||||
|
constexpr uint32_t kNumRoomBlocksets = 82;
|
||||||
|
constexpr uint32_t kNumSpritesets = 144;
|
||||||
|
constexpr uint32_t kNumPalettesets = 72;
|
||||||
|
constexpr uint32_t kEntranceGfxGroup = 0x5D97;
|
||||||
|
|
||||||
|
// TODO: Verify what this was used for in ZS
|
||||||
|
constexpr uint32_t kMaxGraphics = 0xC3FB5;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Different versions of the game supported by the Rom class.
|
* @brief Different versions of the game supported by the Rom class.
|
||||||
*/
|
*/
|
||||||
@@ -111,53 +129,12 @@ static const std::map<Z3_Version, VersionConstants> kVersionConstantsMap = {
|
|||||||
{Z3_Version::RANDO, {}},
|
{Z3_Version::RANDO, {}},
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr uint32_t kNumGfxSheets = 223;
|
|
||||||
constexpr uint32_t kNumLinkSheets = 14;
|
|
||||||
constexpr uint32_t kTile16Ptr = 0x78000;
|
|
||||||
constexpr uint32_t kNormalGfxSpaceStart = 0x87000;
|
|
||||||
constexpr uint32_t kNormalGfxSpaceEnd = 0xC4200;
|
|
||||||
constexpr uint32_t kFontSpriteLocation = 0x70000;
|
|
||||||
constexpr uint32_t kGfxGroupsPointer = 0x6237;
|
|
||||||
constexpr uint32_t kUncompressedSheetSize = 0x0800;
|
|
||||||
constexpr uint32_t kNumMainBlocksets = 37;
|
|
||||||
constexpr uint32_t kNumRoomBlocksets = 82;
|
|
||||||
constexpr uint32_t kNumSpritesets = 144;
|
|
||||||
constexpr uint32_t kNumPalettesets = 72;
|
|
||||||
constexpr uint32_t kEntranceGfxGroup = 0x5D97;
|
|
||||||
|
|
||||||
// TODO: Verify what this was used for in ZS
|
|
||||||
constexpr uint32_t kMaxGraphics = 0xC3FB5;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The Rom class is used to load, save, and modify Rom data.
|
* @brief The Rom class is used to load, save, and modify Rom data.
|
||||||
*/
|
*/
|
||||||
class Rom {
|
class Rom {
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* @brief Loads the players 4bpp graphics sheet from Rom data.
|
|
||||||
*/
|
|
||||||
absl::Status LoadLinkGraphics();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This function iterates over all graphics sheets in the Rom and loads
|
|
||||||
* them into memory. Depending on the sheet's index, it may be uncompressed or
|
|
||||||
* compressed using the LC-LZ2 algorithm. The uncompressed sheets are 3 bits
|
|
||||||
* per pixel (BPP), while the compressed sheets are 4 BPP. The loaded graphics
|
|
||||||
* data is converted to 8 BPP and stored in a bitmap.
|
|
||||||
*
|
|
||||||
* The graphics sheets are divided into the following ranges:
|
|
||||||
*
|
|
||||||
* | Range | Compression Type | Decompressed Size | Number of Chars |
|
|
||||||
* |---------|------------------|------------------|-----------------|
|
|
||||||
* | 0-112 | Compressed 3bpp BGR | 0x600 chars | Decompressed each |
|
|
||||||
* | 113-114 | Compressed 2bpp | 0x800 chars | Decompressed each |
|
|
||||||
* | 115-126 | Uncompressed 3bpp sprites | 0x600 chars | Each |
|
|
||||||
* | 127-217 | Compressed 3bpp sprites | 0x600 chars | Decompressed each |
|
|
||||||
* | 218-222 | Compressed 2bpp | 0x800 chars | Decompressed each |
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
absl::Status LoadAllGraphicsData(bool defer_render = false);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load Rom data from a file.
|
* Load Rom data from a file.
|
||||||
*
|
*
|
||||||
@@ -181,8 +158,6 @@ class Rom {
|
|||||||
absl::Status SaveToFile(bool backup, bool save_new = false,
|
absl::Status SaveToFile(bool backup, bool save_new = false,
|
||||||
std::string filename = "");
|
std::string filename = "");
|
||||||
|
|
||||||
absl::Status SaveAllGraphicsData();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the given palette to the Rom if any of its colors have been modified.
|
* Saves the given palette to the Rom if any of its colors have been modified.
|
||||||
*
|
*
|
||||||
@@ -222,7 +197,7 @@ class Rom {
|
|||||||
/**
|
/**
|
||||||
* @brief Precondition check for reading and writing to the Rom.
|
* @brief Precondition check for reading and writing to the Rom.
|
||||||
*/
|
*/
|
||||||
absl::Status ReadWritePreconditions() {
|
absl::Status ReadWritePreconditions() const {
|
||||||
if (!is_loaded_) {
|
if (!is_loaded_) {
|
||||||
return absl::FailedPreconditionError("ROM file not loaded");
|
return absl::FailedPreconditionError("ROM file not loaded");
|
||||||
}
|
}
|
||||||
@@ -233,7 +208,6 @@ class Rom {
|
|||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read functions
|
|
||||||
absl::StatusOr<uint8_t> ReadByte(int offset) {
|
absl::StatusOr<uint8_t> ReadByte(int offset) {
|
||||||
RETURN_IF_ERROR(ReadWritePreconditions());
|
RETURN_IF_ERROR(ReadWritePreconditions());
|
||||||
if (offset >= static_cast<int>(rom_data_.size())) {
|
if (offset >= static_cast<int>(rom_data_.size())) {
|
||||||
@@ -251,10 +225,6 @@ class Rom {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t toint16(int offset) {
|
|
||||||
return (uint16_t)(rom_data_[offset] | (rom_data_[offset + 1] << 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::StatusOr<uint32_t> ReadLong(int offset) {
|
absl::StatusOr<uint32_t> ReadLong(int offset) {
|
||||||
RETURN_IF_ERROR(ReadWritePreconditions());
|
RETURN_IF_ERROR(ReadWritePreconditions());
|
||||||
if (offset + 2 >= static_cast<int>(rom_data_.size())) {
|
if (offset + 2 >= static_cast<int>(rom_data_.size())) {
|
||||||
@@ -266,7 +236,7 @@ class Rom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::StatusOr<std::vector<uint8_t>> ReadByteVector(uint32_t offset,
|
absl::StatusOr<std::vector<uint8_t>> ReadByteVector(uint32_t offset,
|
||||||
uint32_t length) {
|
uint32_t length) const {
|
||||||
RETURN_IF_ERROR(ReadWritePreconditions());
|
RETURN_IF_ERROR(ReadWritePreconditions());
|
||||||
if (offset + length > static_cast<uint32_t>(rom_data_.size())) {
|
if (offset + length > static_cast<uint32_t>(rom_data_.size())) {
|
||||||
return absl::OutOfRangeError("Offset and length out of range");
|
return absl::OutOfRangeError("Offset and length out of range");
|
||||||
@@ -281,7 +251,7 @@ class Rom {
|
|||||||
absl::StatusOr<gfx::Tile16> ReadTile16(uint32_t tile16_id) {
|
absl::StatusOr<gfx::Tile16> ReadTile16(uint32_t tile16_id) {
|
||||||
// Skip 8 bytes per tile.
|
// Skip 8 bytes per tile.
|
||||||
auto tpos = kTile16Ptr + (tile16_id * 0x08);
|
auto tpos = kTile16Ptr + (tile16_id * 0x08);
|
||||||
gfx::Tile16 tile16;
|
gfx::Tile16 tile16 = {};
|
||||||
ASSIGN_OR_RETURN(auto new_tile0, ReadWord(tpos))
|
ASSIGN_OR_RETURN(auto new_tile0, ReadWord(tpos))
|
||||||
tile16.tile0_ = gfx::WordToTileInfo(new_tile0);
|
tile16.tile0_ = gfx::WordToTileInfo(new_tile0);
|
||||||
tpos += 2;
|
tpos += 2;
|
||||||
@@ -309,17 +279,6 @@ class Rom {
|
|||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write functions
|
|
||||||
absl::Status Write(int addr, int value) {
|
|
||||||
if (addr >= static_cast<int>(rom_data_.size())) {
|
|
||||||
return absl::InvalidArgumentError(absl::StrFormat(
|
|
||||||
"Attempt to write %d value failed, address %d out of range", value,
|
|
||||||
addr));
|
|
||||||
}
|
|
||||||
rom_data_[addr] = value;
|
|
||||||
return absl::OkStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Status WriteByte(int addr, uint8_t value) {
|
absl::Status WriteByte(int addr, uint8_t value) {
|
||||||
RETURN_IF_ERROR(ReadWritePreconditions());
|
RETURN_IF_ERROR(ReadWritePreconditions());
|
||||||
if (addr >= static_cast<int>(rom_data_.size())) {
|
if (addr >= static_cast<int>(rom_data_.size())) {
|
||||||
@@ -419,9 +378,7 @@ class Rom {
|
|||||||
|
|
||||||
uint8_t& operator[](unsigned long i) {
|
uint8_t& operator[](unsigned long i) {
|
||||||
if (i > size_) {
|
if (i > size_) {
|
||||||
std::cout << "ROM: Index " << i << " out of bounds, size: " << size_
|
throw std::out_of_range("Rom index out of range");
|
||||||
<< std::endl;
|
|
||||||
return rom_data_[0];
|
|
||||||
}
|
}
|
||||||
return rom_data_[i];
|
return rom_data_[i];
|
||||||
}
|
}
|
||||||
@@ -434,14 +391,10 @@ class Rom {
|
|||||||
return is_loaded_;
|
return is_loaded_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Full graphical data for the game
|
|
||||||
std::vector<uint8_t> graphics_buffer() const { return graphics_buffer_; }
|
|
||||||
|
|
||||||
auto title() const { return title_; }
|
auto title() const { return title_; }
|
||||||
auto size() const { return size_; }
|
auto size() const { return size_; }
|
||||||
auto data() const { return rom_data_.data(); }
|
auto data() const { return rom_data_.data(); }
|
||||||
auto mutable_data() { return rom_data_.data(); }
|
auto mutable_data() { return rom_data_.data(); }
|
||||||
|
|
||||||
auto begin() { return rom_data_.begin(); }
|
auto begin() { return rom_data_.begin(); }
|
||||||
auto end() { return rom_data_.end(); }
|
auto end() { return rom_data_.end(); }
|
||||||
|
|
||||||
@@ -450,12 +403,9 @@ class Rom {
|
|||||||
auto filename() const { return filename_; }
|
auto filename() const { return filename_; }
|
||||||
auto set_filename(std::string name) { filename_ = name; }
|
auto set_filename(std::string name) { filename_ = name; }
|
||||||
|
|
||||||
auto link_graphics() { return link_graphics_; }
|
std::vector<uint8_t> graphics_buffer() const { return graphics_buffer_; }
|
||||||
auto mutable_link_graphics() { return &link_graphics_; }
|
auto mutable_graphics_buffer() { return &graphics_buffer_; }
|
||||||
auto gfx_sheets() { return graphics_sheets_; }
|
auto palette_group() const { return palette_groups_; }
|
||||||
auto mutable_gfx_sheets() { return &graphics_sheets_; }
|
|
||||||
|
|
||||||
auto palette_group() { return palette_groups_; }
|
|
||||||
auto mutable_palette_group() { return &palette_groups_; }
|
auto mutable_palette_group() { return &palette_groups_; }
|
||||||
auto dungeon_palette(int i) { return palette_groups_.dungeon_main[i]; }
|
auto dungeon_palette(int i) { return palette_groups_.dungeon_main[i]; }
|
||||||
auto mutable_dungeon_palette(int i) {
|
auto mutable_dungeon_palette(int i) {
|
||||||
@@ -482,7 +432,7 @@ class Rom {
|
|||||||
private:
|
private:
|
||||||
virtual absl::Status WriteHelper(const WriteAction& action) {
|
virtual absl::Status WriteHelper(const WriteAction& action) {
|
||||||
if (std::holds_alternative<uint8_t>(action.value)) {
|
if (std::holds_alternative<uint8_t>(action.value)) {
|
||||||
return Write(action.address, std::get<uint8_t>(action.value));
|
return WriteByte(action.address, std::get<uint8_t>(action.value));
|
||||||
} else if (std::holds_alternative<uint16_t>(action.value) ||
|
} else if (std::holds_alternative<uint16_t>(action.value) ||
|
||||||
std::holds_alternative<short>(action.value)) {
|
std::holds_alternative<short>(action.value)) {
|
||||||
return WriteShort(action.address, std::get<uint16_t>(action.value));
|
return WriteShort(action.address, std::get<uint16_t>(action.value));
|
||||||
@@ -538,12 +488,6 @@ class Rom {
|
|||||||
// Full contiguous graphics space
|
// Full contiguous graphics space
|
||||||
std::vector<uint8_t> graphics_buffer_;
|
std::vector<uint8_t> graphics_buffer_;
|
||||||
|
|
||||||
// All graphics sheets in the game
|
|
||||||
std::array<gfx::Bitmap, kNumGfxSheets> graphics_sheets_;
|
|
||||||
|
|
||||||
// All graphics sheets for Link
|
|
||||||
std::array<gfx::Bitmap, kNumLinkSheets> link_graphics_;
|
|
||||||
|
|
||||||
// Label manager for unique resource names.
|
// Label manager for unique resource names.
|
||||||
ResourceLabelManager resource_label_manager_;
|
ResourceLabelManager resource_label_manager_;
|
||||||
|
|
||||||
@@ -554,6 +498,44 @@ class Rom {
|
|||||||
Z3_Version version_ = Z3_Version::US;
|
Z3_Version version_ = Z3_Version::US;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GraphicsSheetManager {
|
||||||
|
public:
|
||||||
|
static GraphicsSheetManager& GetInstance() {
|
||||||
|
static GraphicsSheetManager instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
GraphicsSheetManager() = default;
|
||||||
|
virtual ~GraphicsSheetManager() = default;
|
||||||
|
std::array<gfx::Bitmap, kNumGfxSheets>& gfx_sheets() { return gfx_sheets_; }
|
||||||
|
auto gfx_sheet(int i) { return gfx_sheets_[i]; }
|
||||||
|
auto mutable_gfx_sheet(int i) { return &gfx_sheets_[i]; }
|
||||||
|
auto mutable_gfx_sheets() { return &gfx_sheets_; }
|
||||||
|
private:
|
||||||
|
std::array<gfx::Bitmap, kNumGfxSheets> gfx_sheets_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function iterates over all graphics sheets in the Rom and loads
|
||||||
|
* them into memory. Depending on the sheet's index, it may be uncompressed or
|
||||||
|
* compressed using the LC-LZ2 algorithm. The uncompressed sheets are 3 bits
|
||||||
|
* per pixel (BPP), while the compressed sheets are 4 BPP. The loaded graphics
|
||||||
|
* data is converted to 8 BPP and stored in a bitmap.
|
||||||
|
*
|
||||||
|
* The graphics sheets are divided into the following ranges:
|
||||||
|
*
|
||||||
|
* | Range | Compression Type | Decompressed Size | Number of Chars |
|
||||||
|
* |---------|------------------|------------------|-----------------|
|
||||||
|
* | 0-112 | Compressed 3bpp BGR | 0x600 chars | Decompressed each |
|
||||||
|
* | 113-114 | Compressed 2bpp | 0x800 chars | Decompressed each |
|
||||||
|
* | 115-126 | Uncompressed 3bpp sprites | 0x600 chars | Each |
|
||||||
|
* | 127-217 | Compressed 3bpp sprites | 0x600 chars | Decompressed each |
|
||||||
|
* | 218-222 | Compressed 2bpp | 0x800 chars | Decompressed each |
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
absl::StatusOr<std::array<gfx::Bitmap, kNumGfxSheets>> LoadAllGraphicsData(Rom& rom, bool defer_render = false);
|
||||||
|
|
||||||
|
absl::Status SaveAllGraphicsData(Rom& rom, std::array<gfx::Bitmap, kNumGfxSheets>& gfx_sheets);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Loads 2bpp graphics from Rom data.
|
* @brief Loads 2bpp graphics from Rom data.
|
||||||
*
|
*
|
||||||
@@ -564,6 +546,11 @@ class Rom {
|
|||||||
*/
|
*/
|
||||||
absl::StatusOr<std::vector<uint8_t>> Load2BppGraphics(const Rom& rom);
|
absl::StatusOr<std::vector<uint8_t>> Load2BppGraphics(const Rom& rom);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Loads the players 4bpp graphics sheet from Rom data.
|
||||||
|
*/
|
||||||
|
absl::StatusOr<std::array<gfx::Bitmap, kNumLinkSheets>> LoadLinkGraphics(const Rom& rom);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A class to hold a shared pointer to a Rom object.
|
* @brief A class to hold a shared pointer to a Rom object.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ class GameEntity {
|
|||||||
kProperties = 7,
|
kProperties = 7,
|
||||||
kDungeonSprite = 8,
|
kDungeonSprite = 8,
|
||||||
} entity_type_;
|
} entity_type_;
|
||||||
int x_;
|
int x_ = 0;
|
||||||
int y_;
|
int y_ = 0;
|
||||||
int game_x_;
|
int game_x_ = 0;
|
||||||
int game_y_;
|
int game_y_ = 0;
|
||||||
int entity_id_;
|
int entity_id_ = 0;
|
||||||
uint16_t map_id_;
|
uint16_t map_id_ = 0;
|
||||||
|
|
||||||
auto set_x(int x) { x_ = x; }
|
auto set_x(int x) { x_ = x; }
|
||||||
auto set_y(int y) { y_ = y; }
|
auto set_y(int y) { y_ = y; }
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ void DungeonObjectRenderer::UpdateObjectBitmap() {
|
|||||||
int x = column * 8;
|
int x = column * 8;
|
||||||
int y = row * 8;
|
int y = row * 8;
|
||||||
|
|
||||||
auto sheet = rom()->mutable_gfx_sheets()->at(vram_.sheets[sheet_number]);
|
auto sheet = GraphicsSheetManager::GetInstance().mutable_gfx_sheets()->at(vram_.sheets[sheet_number]);
|
||||||
|
|
||||||
// Copy the tile from VRAM using the read tile_id
|
// Copy the tile from VRAM using the read tile_id
|
||||||
sheet.Get8x8Tile(tile_id, x, y, tilemap_, tilemap_offset);
|
sheet.Get8x8Tile(tile_id, x, y, tilemap_, tilemap_offset);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace yaze {
|
|||||||
namespace zelda3 {
|
namespace zelda3 {
|
||||||
|
|
||||||
struct PseudoVram {
|
struct PseudoVram {
|
||||||
std::array<uint8_t, 16> sheets;
|
std::array<uint8_t, 16> sheets = { 0 };
|
||||||
std::vector<gfx::SnesPalette> palettes;
|
std::vector<gfx::SnesPalette> palettes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -220,37 +220,37 @@ class RoomEntrance {
|
|||||||
RETURN_IF_ERROR(rom.WriteShort(
|
RETURN_IF_ERROR(rom.WriteShort(
|
||||||
kEntranceCameraYTrigger + (entrance_id * 2), camera_trigger_y_));
|
kEntranceCameraYTrigger + (entrance_id * 2), camera_trigger_y_));
|
||||||
RETURN_IF_ERROR(rom.WriteShort(kEntranceExit + (entrance_id * 2), exit_));
|
RETURN_IF_ERROR(rom.WriteShort(kEntranceExit + (entrance_id * 2), exit_));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntranceBlockset + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kEntranceBlockset + entrance_id,
|
||||||
(uint8_t)(blockset_ & 0xFF)));
|
(uint8_t)(blockset_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom.Write(kEntranceMusic + entrance_id, (uint8_t)(music_ & 0xFF)));
|
rom.WriteByte(kEntranceMusic + entrance_id, (uint8_t)(music_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntranceDungeon + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kEntranceDungeon + entrance_id,
|
||||||
(uint8_t)(dungeon_id_ & 0xFF)));
|
(uint8_t)(dungeon_id_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom.Write(kEntranceDoor + entrance_id, (uint8_t)(door_ & 0xFF)));
|
rom.WriteByte(kEntranceDoor + entrance_id, (uint8_t)(door_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom.Write(kEntranceFloor + entrance_id, (uint8_t)(floor_ & 0xFF)));
|
rom.WriteByte(kEntranceFloor + entrance_id, (uint8_t)(floor_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntranceLadderBG + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kEntranceLadderBG + entrance_id,
|
||||||
(uint8_t)(ladder_bg_ & 0xFF)));
|
(uint8_t)(ladder_bg_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntrancescrolling + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kEntrancescrolling + entrance_id,
|
||||||
(uint8_t)(scrolling_ & 0xFF)));
|
(uint8_t)(scrolling_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntranceScrollQuadrant + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kEntranceScrollQuadrant + entrance_id,
|
||||||
(uint8_t)(scroll_quadrant_ & 0xFF)));
|
(uint8_t)(scroll_quadrant_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntranceScrollEdge + 0 + (entrance_id * 8),
|
RETURN_IF_ERROR(rom.WriteByte(kEntranceScrollEdge + 0 + (entrance_id * 8),
|
||||||
camera_boundary_qn_));
|
camera_boundary_qn_));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntranceScrollEdge + 1 + (entrance_id * 8),
|
RETURN_IF_ERROR(rom.WriteByte(kEntranceScrollEdge + 1 + (entrance_id * 8),
|
||||||
camera_boundary_fn_));
|
camera_boundary_fn_));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntranceScrollEdge + 2 + (entrance_id * 8),
|
RETURN_IF_ERROR(rom.WriteByte(kEntranceScrollEdge + 2 + (entrance_id * 8),
|
||||||
camera_boundary_qs_));
|
camera_boundary_qs_));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntranceScrollEdge + 3 + (entrance_id * 8),
|
RETURN_IF_ERROR(rom.WriteByte(kEntranceScrollEdge + 3 + (entrance_id * 8),
|
||||||
camera_boundary_fs_));
|
camera_boundary_fs_));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntranceScrollEdge + 4 + (entrance_id * 8),
|
RETURN_IF_ERROR(rom.WriteByte(kEntranceScrollEdge + 4 + (entrance_id * 8),
|
||||||
camera_boundary_qw_));
|
camera_boundary_qw_));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntranceScrollEdge + 5 + (entrance_id * 8),
|
RETURN_IF_ERROR(rom.WriteByte(kEntranceScrollEdge + 5 + (entrance_id * 8),
|
||||||
camera_boundary_fw_));
|
camera_boundary_fw_));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntranceScrollEdge + 6 + (entrance_id * 8),
|
RETURN_IF_ERROR(rom.WriteByte(kEntranceScrollEdge + 6 + (entrance_id * 8),
|
||||||
camera_boundary_qe_));
|
camera_boundary_qe_));
|
||||||
RETURN_IF_ERROR(rom.Write(kEntranceScrollEdge + 7 + (entrance_id * 8),
|
RETURN_IF_ERROR(rom.WriteByte(kEntranceScrollEdge + 7 + (entrance_id * 8),
|
||||||
camera_boundary_fe_));
|
camera_boundary_fe_));
|
||||||
} else {
|
} else {
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
@@ -271,45 +271,45 @@ class RoomEntrance {
|
|||||||
camera_trigger_y_));
|
camera_trigger_y_));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom.WriteShort(kStartingEntranceexit + (entrance_id * 2), exit_));
|
rom.WriteShort(kStartingEntranceexit + (entrance_id * 2), exit_));
|
||||||
RETURN_IF_ERROR(rom.Write(kStartingEntranceBlockset + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kStartingEntranceBlockset + entrance_id,
|
||||||
(uint8_t)(blockset_ & 0xFF)));
|
(uint8_t)(blockset_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(rom.Write(kStartingEntrancemusic + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kStartingEntrancemusic + entrance_id,
|
||||||
(uint8_t)(music_ & 0xFF)));
|
(uint8_t)(music_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(rom.Write(kStartingEntranceDungeon + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kStartingEntranceDungeon + entrance_id,
|
||||||
(uint8_t)(dungeon_id_ & 0xFF)));
|
(uint8_t)(dungeon_id_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(rom.Write(kStartingEntranceDoor + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kStartingEntranceDoor + entrance_id,
|
||||||
(uint8_t)(door_ & 0xFF)));
|
(uint8_t)(door_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(rom.Write(kStartingEntranceFloor + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kStartingEntranceFloor + entrance_id,
|
||||||
(uint8_t)(floor_ & 0xFF)));
|
(uint8_t)(floor_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(rom.Write(kStartingEntranceLadderBG + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kStartingEntranceLadderBG + entrance_id,
|
||||||
(uint8_t)(ladder_bg_ & 0xFF)));
|
(uint8_t)(ladder_bg_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(rom.Write(kStartingEntrancescrolling + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kStartingEntrancescrolling + entrance_id,
|
||||||
(uint8_t)(scrolling_ & 0xFF)));
|
(uint8_t)(scrolling_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(rom.Write(kStartingEntranceScrollQuadrant + entrance_id,
|
RETURN_IF_ERROR(rom.WriteByte(kStartingEntranceScrollQuadrant + entrance_id,
|
||||||
(uint8_t)(scroll_quadrant_ & 0xFF)));
|
(uint8_t)(scroll_quadrant_ & 0xFF)));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom.Write(kStartingEntranceScrollEdge + 0 + (entrance_id * 8),
|
rom.WriteByte(kStartingEntranceScrollEdge + 0 + (entrance_id * 8),
|
||||||
camera_boundary_qn_));
|
camera_boundary_qn_));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom.Write(kStartingEntranceScrollEdge + 1 + (entrance_id * 8),
|
rom.WriteByte(kStartingEntranceScrollEdge + 1 + (entrance_id * 8),
|
||||||
camera_boundary_fn_));
|
camera_boundary_fn_));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom.Write(kStartingEntranceScrollEdge + 2 + (entrance_id * 8),
|
rom.WriteByte(kStartingEntranceScrollEdge + 2 + (entrance_id * 8),
|
||||||
camera_boundary_qs_));
|
camera_boundary_qs_));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom.Write(kStartingEntranceScrollEdge + 3 + (entrance_id * 8),
|
rom.WriteByte(kStartingEntranceScrollEdge + 3 + (entrance_id * 8),
|
||||||
camera_boundary_fs_));
|
camera_boundary_fs_));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom.Write(kStartingEntranceScrollEdge + 4 + (entrance_id * 8),
|
rom.WriteByte(kStartingEntranceScrollEdge + 4 + (entrance_id * 8),
|
||||||
camera_boundary_qw_));
|
camera_boundary_qw_));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom.Write(kStartingEntranceScrollEdge + 5 + (entrance_id * 8),
|
rom.WriteByte(kStartingEntranceScrollEdge + 5 + (entrance_id * 8),
|
||||||
camera_boundary_fw_));
|
camera_boundary_fw_));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom.Write(kStartingEntranceScrollEdge + 6 + (entrance_id * 8),
|
rom.WriteByte(kStartingEntranceScrollEdge + 6 + (entrance_id * 8),
|
||||||
camera_boundary_qe_));
|
camera_boundary_qe_));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom.Write(kStartingEntranceScrollEdge + 7 + (entrance_id * 8),
|
rom.WriteByte(kStartingEntranceScrollEdge + 7 + (entrance_id * 8),
|
||||||
camera_boundary_fe_));
|
camera_boundary_fe_));
|
||||||
}
|
}
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ absl::Status Overworld::Load(Rom &rom) {
|
|||||||
overworld_maps_.emplace_back(map_index, rom_);
|
overworld_maps_.emplace_back(map_index, rom_);
|
||||||
|
|
||||||
FetchLargeMaps();
|
FetchLargeMaps();
|
||||||
LoadEntrances();
|
RETURN_IF_ERROR(LoadEntrances());
|
||||||
|
RETURN_IF_ERROR(LoadHoles());
|
||||||
RETURN_IF_ERROR(LoadExits());
|
RETURN_IF_ERROR(LoadExits());
|
||||||
RETURN_IF_ERROR(LoadItems());
|
RETURN_IF_ERROR(LoadItems());
|
||||||
RETURN_IF_ERROR(LoadSprites());
|
RETURN_IF_ERROR(LoadSprites());
|
||||||
@@ -281,6 +282,7 @@ absl::Status Overworld::LoadOverworldMaps() {
|
|||||||
|
|
||||||
// Wait for all tasks to complete and check their results
|
// Wait for all tasks to complete and check their results
|
||||||
for (auto &future : futures) {
|
for (auto &future : futures) {
|
||||||
|
future.wait();
|
||||||
RETURN_IF_ERROR(future.get());
|
RETURN_IF_ERROR(future.get());
|
||||||
}
|
}
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
@@ -293,7 +295,7 @@ void Overworld::LoadTileTypes() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overworld::LoadEntrances() {
|
absl::Status Overworld::LoadEntrances() {
|
||||||
int ow_entrance_map_ptr = kOverworldEntranceMap;
|
int ow_entrance_map_ptr = kOverworldEntranceMap;
|
||||||
int ow_entrance_pos_ptr = kOverworldEntrancePos;
|
int ow_entrance_pos_ptr = kOverworldEntrancePos;
|
||||||
int ow_entrance_id_ptr = kOverworldEntranceEntranceId;
|
int ow_entrance_id_ptr = kOverworldEntranceEntranceId;
|
||||||
@@ -307,9 +309,9 @@ void Overworld::LoadEntrances() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < num_entrances; i++) {
|
for (int i = 0; i < num_entrances; i++) {
|
||||||
short map_id = rom()->toint16(ow_entrance_map_ptr + (i * 2));
|
ASSIGN_OR_RETURN(auto map_id, rom()->ReadWord(ow_entrance_map_ptr + (i * 2)));
|
||||||
uint16_t map_pos = rom()->toint16(ow_entrance_pos_ptr + (i * 2));
|
ASSIGN_OR_RETURN(auto map_pos, rom()->ReadWord(ow_entrance_pos_ptr + (i * 2)));
|
||||||
uint8_t entrance_id = rom_[ow_entrance_id_ptr + i];
|
ASSIGN_OR_RETURN(auto entrance_id, rom()->ReadByte(ow_entrance_id_ptr + i));
|
||||||
int p = map_pos >> 1;
|
int p = map_pos >> 1;
|
||||||
int x = (p % 64);
|
int x = (p % 64);
|
||||||
int y = (p >> 6);
|
int y = (p >> 6);
|
||||||
@@ -323,20 +325,25 @@ void Overworld::LoadEntrances() {
|
|||||||
deleted);
|
deleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 0x13; i++) {
|
|
||||||
auto map_id = (short)((rom_[kOverworldHoleArea + (i * 2) + 1] << 8) +
|
return absl::OkStatus();
|
||||||
(rom_[kOverworldHoleArea + (i * 2)]));
|
}
|
||||||
auto map_pos = (short)((rom_[kOverworldHolePos + (i * 2) + 1] << 8) +
|
|
||||||
(rom_[kOverworldHolePos + (i * 2)]));
|
absl::Status Overworld::LoadHoles() {
|
||||||
uint8_t entrance_id = (rom_[kOverworldHoleEntrance + i]);
|
constexpr int kNumHoles = 0x13;
|
||||||
|
for (int i = 0; i < kNumHoles; i++) {
|
||||||
|
ASSIGN_OR_RETURN(auto map_id, rom()->ReadWord(kOverworldHoleArea + (i * 2)));
|
||||||
|
ASSIGN_OR_RETURN(auto map_pos, rom()->ReadWord(kOverworldHolePos + (i * 2)));
|
||||||
|
ASSIGN_OR_RETURN(auto entrance_id, rom()->ReadByte(kOverworldHoleEntrance + i));
|
||||||
int p = (map_pos + 0x400) >> 1;
|
int p = (map_pos + 0x400) >> 1;
|
||||||
int x = (p % 64);
|
int x = (p % 64);
|
||||||
int y = (p >> 6);
|
int y = (p >> 6);
|
||||||
all_holes_.emplace_back(
|
all_holes_.emplace_back(
|
||||||
(x * 16) + (((map_id % 64) - (((map_id % 64) / 8) * 8)) * 512),
|
(x * 16) + (((map_id % 64) - (((map_id % 64) / 8) * 8)) * 512),
|
||||||
(y * 16) + (((map_id % 64) / 8) * 512), entrance_id, map_id,
|
(y * 16) + (((map_id % 64) / 8) * 512), entrance_id, map_id,
|
||||||
(uint16_t)(map_pos + 0x400), true);
|
(uint16_t)(map_pos + 0x400), true);
|
||||||
}
|
}
|
||||||
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Overworld::LoadExits() {
|
absl::Status Overworld::LoadExits() {
|
||||||
@@ -447,13 +454,21 @@ absl::Status Overworld::LoadItems() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Overworld::LoadSprites() {
|
absl::Status Overworld::LoadSprites() {
|
||||||
for (int i = 0; i < 3; i++) {
|
std::vector<std::future<absl::Status>> futures;
|
||||||
all_sprites_.emplace_back();
|
futures.emplace_back(std::async(std::launch::async, [this]() {
|
||||||
}
|
return LoadSpritesFromMap(kOverworldSpritesBeginning, 64, 0);
|
||||||
|
}));
|
||||||
|
futures.emplace_back(std::async(std::launch::async, [this]() {
|
||||||
|
return LoadSpritesFromMap(kOverworldSpritesZelda, 144, 1);
|
||||||
|
}));
|
||||||
|
futures.emplace_back(std::async(std::launch::async, [this]() {
|
||||||
|
return LoadSpritesFromMap(kOverworldSpritesAgahnim, 144, 2);
|
||||||
|
}));
|
||||||
|
|
||||||
RETURN_IF_ERROR(LoadSpritesFromMap(kOverworldSpritesBeginning, 64, 0));
|
for (auto& future : futures) {
|
||||||
RETURN_IF_ERROR(LoadSpritesFromMap(kOverworldSpritesZelda, 144, 1));
|
future.wait();
|
||||||
RETURN_IF_ERROR(LoadSpritesFromMap(kOverworldSpritesAgahnim, 144, 2));
|
RETURN_IF_ERROR(future.get());
|
||||||
|
}
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,8 +499,8 @@ absl::Status Overworld::LoadSpritesFromMap(int sprites_per_gamestate_ptr,
|
|||||||
|
|
||||||
int realX = ((b2 & 0x3F) * 16) + mapX * 512;
|
int realX = ((b2 & 0x3F) * 16) + mapX * 512;
|
||||||
int realY = ((b1 & 0x3F) * 16) + mapY * 512;
|
int realY = ((b1 & 0x3F) * 16) + mapY * 512;
|
||||||
auto current_gfx = overworld_maps_[i].current_graphics();
|
all_sprites_[game_state].emplace_back(*overworld_maps_[i].mutable_current_graphics(),
|
||||||
all_sprites_[game_state].emplace_back(current_gfx, (uint8_t)i, b3,
|
(uint8_t)i, b3,
|
||||||
(uint8_t)(b2 & 0x3F),
|
(uint8_t)(b2 & 0x3F),
|
||||||
(uint8_t)(b1 & 0x3F), realX, realY);
|
(uint8_t)(b1 & 0x3F), realX, realY);
|
||||||
all_sprites_[game_state][i].Draw();
|
all_sprites_[game_state][i].Draw();
|
||||||
@@ -659,7 +674,7 @@ absl::Status Overworld::SaveLargeMaps() {
|
|||||||
|
|
||||||
// Always write the map parent since it should not matter
|
// Always write the map parent since it should not matter
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom()->Write(kOverworldMapParentId + i, overworld_maps_[i].parent()))
|
rom()->WriteByte(kOverworldMapParentId + i, overworld_maps_[i].parent()))
|
||||||
|
|
||||||
if (std::find(checked_map.begin(), checked_map.end(), i) !=
|
if (std::find(checked_map.begin(), checked_map.end(), i) !=
|
||||||
checked_map.end()) {
|
checked_map.end()) {
|
||||||
@@ -1322,10 +1337,10 @@ absl::Status Overworld::SaveMap16Expanded() {
|
|||||||
RETURN_IF_ERROR(rom()->WriteShort(core::SnesToPc(0x02FE33),
|
RETURN_IF_ERROR(rom()->WriteShort(core::SnesToPc(0x02FE33),
|
||||||
core::PcToSnes(kMap16TilesExpanded + 6)));
|
core::PcToSnes(kMap16TilesExpanded + 6)));
|
||||||
|
|
||||||
RETURN_IF_ERROR(rom()->Write(
|
RETURN_IF_ERROR(rom()->WriteByte(
|
||||||
core::SnesToPc(0x02FD28),
|
core::SnesToPc(0x02FD28),
|
||||||
static_cast<uint8_t>(core::PcToSnes(kMap16TilesExpanded) >> 16)));
|
static_cast<uint8_t>(core::PcToSnes(kMap16TilesExpanded) >> 16)));
|
||||||
RETURN_IF_ERROR(rom()->Write(
|
RETURN_IF_ERROR(rom()->WriteByte(
|
||||||
core::SnesToPc(0x02FD39),
|
core::SnesToPc(0x02FD39),
|
||||||
static_cast<uint8_t>(core::PcToSnes(kMap16TilesExpanded) >> 16)));
|
static_cast<uint8_t>(core::PcToSnes(kMap16TilesExpanded) >> 16)));
|
||||||
|
|
||||||
@@ -1392,7 +1407,7 @@ absl::Status Overworld::SaveExits() {
|
|||||||
for (int i = 0; i < kNumOverworldExits; i++) {
|
for (int i = 0; i < kNumOverworldExits; i++) {
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom()->WriteShort(OWExitRoomId + (i * 2), all_exits_[i].room_id_));
|
rom()->WriteShort(OWExitRoomId + (i * 2), all_exits_[i].room_id_));
|
||||||
RETURN_IF_ERROR(rom()->Write(OWExitMapId + i, all_exits_[i].map_id_));
|
RETURN_IF_ERROR(rom()->WriteByte(OWExitMapId + i, all_exits_[i].map_id_));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
rom()->WriteShort(OWExitVram + (i * 2), all_exits_[i].map_pos_));
|
rom()->WriteShort(OWExitVram + (i * 2), all_exits_[i].map_pos_));
|
||||||
RETURN_IF_ERROR(
|
RETURN_IF_ERROR(
|
||||||
|
|||||||
@@ -109,16 +109,19 @@ constexpr int NumberOfMap32 = Map32PerScreen * kNumOverworldMaps;
|
|||||||
*/
|
*/
|
||||||
class Overworld : public SharedRom {
|
class Overworld : public SharedRom {
|
||||||
public:
|
public:
|
||||||
|
Overworld(Rom& rom) : rom_(rom) {}
|
||||||
|
|
||||||
absl::Status Load(Rom &rom);
|
absl::Status Load(Rom &rom);
|
||||||
absl::Status LoadOverworldMaps();
|
absl::Status LoadOverworldMaps();
|
||||||
void LoadTileTypes();
|
void LoadTileTypes();
|
||||||
void LoadEntrances();
|
absl::Status LoadEntrances();
|
||||||
|
absl::Status LoadHoles();
|
||||||
|
|
||||||
absl::Status LoadExits();
|
absl::Status LoadExits();
|
||||||
absl::Status LoadItems();
|
absl::Status LoadItems();
|
||||||
absl::Status LoadSprites();
|
absl::Status LoadSprites();
|
||||||
absl::Status LoadSpritesFromMap(int spriteStart, int spriteCount,
|
absl::Status LoadSpritesFromMap(int sprite_start, int sprite_count,
|
||||||
int spriteIndex);
|
int sprite_index);
|
||||||
|
|
||||||
absl::Status Save(Rom &rom);
|
absl::Status Save(Rom &rom);
|
||||||
absl::Status SaveOverworldMaps();
|
absl::Status SaveOverworldMaps();
|
||||||
@@ -143,7 +146,9 @@ class Overworld : public SharedRom {
|
|||||||
all_entrances_.clear();
|
all_entrances_.clear();
|
||||||
all_exits_.clear();
|
all_exits_.clear();
|
||||||
all_items_.clear();
|
all_items_.clear();
|
||||||
all_sprites_.clear();
|
for (auto& sprites : all_sprites_) {
|
||||||
|
sprites.clear();
|
||||||
|
}
|
||||||
is_loaded_ = false;
|
is_loaded_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +232,7 @@ class Overworld : public SharedRom {
|
|||||||
int &ttpos);
|
int &ttpos);
|
||||||
void DecompressAllMapTiles();
|
void DecompressAllMapTiles();
|
||||||
|
|
||||||
Rom rom_;
|
Rom& rom_;
|
||||||
|
|
||||||
bool is_loaded_ = false;
|
bool is_loaded_ = false;
|
||||||
bool expanded_tile16_ = false;
|
bool expanded_tile16_ = false;
|
||||||
@@ -240,8 +245,8 @@ class Overworld : public SharedRom {
|
|||||||
|
|
||||||
OverworldMapTiles map_tiles_;
|
OverworldMapTiles map_tiles_;
|
||||||
|
|
||||||
std::array<uint8_t, kNumOverworldMaps> map_parent_;
|
std::array<uint8_t, kNumOverworldMaps> map_parent_ = { 0 };
|
||||||
std::array<uint8_t, kNumTileTypes> all_tiles_types_;
|
std::array<uint8_t, kNumTileTypes> all_tiles_types_ = { 0 };
|
||||||
std::vector<gfx::Tile16> tiles16_;
|
std::vector<gfx::Tile16> tiles16_;
|
||||||
std::vector<gfx::Tile32> tiles32_;
|
std::vector<gfx::Tile32> tiles32_;
|
||||||
std::vector<uint16_t> tiles32_list_;
|
std::vector<uint16_t> tiles32_list_;
|
||||||
@@ -251,7 +256,7 @@ class Overworld : public SharedRom {
|
|||||||
std::vector<OverworldEntrance> all_holes_;
|
std::vector<OverworldEntrance> all_holes_;
|
||||||
std::vector<OverworldExit> all_exits_;
|
std::vector<OverworldExit> all_exits_;
|
||||||
std::vector<OverworldItem> all_items_;
|
std::vector<OverworldItem> all_items_;
|
||||||
std::vector<std::vector<Sprite>> all_sprites_;
|
std::array<std::vector<Sprite>, 3> all_sprites_;
|
||||||
std::vector<uint64_t> deleted_entrances_;
|
std::vector<uint64_t> deleted_entrances_;
|
||||||
std::vector<std::vector<uint8_t>> map_data_p1 =
|
std::vector<std::vector<uint8_t>> map_data_p1 =
|
||||||
std::vector<std::vector<uint8_t>>(kNumOverworldMaps);
|
std::vector<std::vector<uint8_t>>(kNumOverworldMaps);
|
||||||
|
|||||||
@@ -71,7 +71,13 @@ void OverworldMap::LoadAreaInfo() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message_id_ = rom_.toint16(kOverworldMessageIds + (parent_ * 2));
|
auto message_id = rom_.ReadWord(kOverworldMessageIds + (parent_ * 2));
|
||||||
|
if (message_id.ok()) {
|
||||||
|
message_id_ = message_id.value();
|
||||||
|
} else {
|
||||||
|
message_id_ = 0;
|
||||||
|
core::logf("Error reading message id for map %d", parent_);
|
||||||
|
}
|
||||||
|
|
||||||
if (index_ < kDarkWorldMapIdStart) {
|
if (index_ < kDarkWorldMapIdStart) {
|
||||||
area_graphics_ = rom_[kAreaGfxIdPtr + parent_];
|
area_graphics_ = rom_[kAreaGfxIdPtr + parent_];
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ class OverworldMap : public gfx::GfxContext {
|
|||||||
auto static_graphics(int i) const { return static_graphics_[i]; }
|
auto static_graphics(int i) const { return static_graphics_[i]; }
|
||||||
auto large_index() const { return large_index_; }
|
auto large_index() const { return large_index_; }
|
||||||
|
|
||||||
|
auto mutable_current_graphics() { return ¤t_gfx_; }
|
||||||
auto mutable_area_graphics() { return &area_graphics_; }
|
auto mutable_area_graphics() { return &area_graphics_; }
|
||||||
auto mutable_area_palette() { return &area_palette_; }
|
auto mutable_area_palette() { return &area_palette_; }
|
||||||
auto mutable_sprite_graphics(int i) { return &sprite_graphics_[i]; }
|
auto mutable_sprite_graphics(int i) { return &sprite_graphics_[i]; }
|
||||||
|
|||||||
@@ -17,10 +17,14 @@ absl::Status Inventory::Create() {
|
|||||||
}
|
}
|
||||||
RETURN_IF_ERROR(BuildTileset())
|
RETURN_IF_ERROR(BuildTileset())
|
||||||
for (int i = 0; i < 0x500; i += 0x08) {
|
for (int i = 0; i < 0x500; i += 0x08) {
|
||||||
tiles_.push_back(gfx::GetTilesInfo(rom()->toint16(i + kBowItemPos)));
|
ASSIGN_OR_RETURN(auto t1, rom()->ReadWord(i + kBowItemPos));
|
||||||
tiles_.push_back(gfx::GetTilesInfo(rom()->toint16(i + kBowItemPos + 0x02)));
|
ASSIGN_OR_RETURN(auto t2, rom()->ReadWord(i + kBowItemPos + 0x02));
|
||||||
tiles_.push_back(gfx::GetTilesInfo(rom()->toint16(i + kBowItemPos + 0x04)));
|
ASSIGN_OR_RETURN(auto t3, rom()->ReadWord(i + kBowItemPos + 0x04));
|
||||||
tiles_.push_back(gfx::GetTilesInfo(rom()->toint16(i + kBowItemPos + 0x08)));
|
ASSIGN_OR_RETURN(auto t4, rom()->ReadWord(i + kBowItemPos + 0x06));
|
||||||
|
tiles_.push_back(gfx::GetTilesInfo(t1));
|
||||||
|
tiles_.push_back(gfx::GetTilesInfo(t2));
|
||||||
|
tiles_.push_back(gfx::GetTilesInfo(t3));
|
||||||
|
tiles_.push_back(gfx::GetTilesInfo(t4));
|
||||||
}
|
}
|
||||||
const int offsets[] = {0x00, 0x08, 0x800, 0x808};
|
const int offsets[] = {0x00, 0x08, 0x800, 0x808};
|
||||||
auto xx = 0;
|
auto xx = 0;
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ static const std::string kSpriteDefaultNames[]{
|
|||||||
class Sprite : public GameEntity {
|
class Sprite : public GameEntity {
|
||||||
public:
|
public:
|
||||||
Sprite() = default;
|
Sprite() = default;
|
||||||
Sprite(std::vector<uint8_t> src, uint8_t overworld_map_id, uint8_t id,
|
Sprite(const std::vector<uint8_t>& src, uint8_t overworld_map_id, uint8_t id,
|
||||||
uint8_t x, uint8_t y, int map_x, int map_y)
|
uint8_t x, uint8_t y, int map_x, int map_y)
|
||||||
: map_id_(static_cast<int>(overworld_map_id)),
|
: map_id_(static_cast<int>(overworld_map_id)),
|
||||||
id_(id),
|
id_(id),
|
||||||
|
|||||||
Reference in New Issue
Block a user