backend-infra-engineer: Release 0.2.2 snapshot
This commit is contained in:
@@ -5,35 +5,34 @@ include(app/gui/gui.cmake)
|
||||
include(app/zelda3/zelda3.cmake)
|
||||
|
||||
if (APPLE)
|
||||
add_executable(
|
||||
yaze
|
||||
MACOSX_BUNDLE
|
||||
app/main.cc
|
||||
app/rom.cc
|
||||
${YAZE_APP_EMU_SRC}
|
||||
${YAZE_APP_CORE_SRC}
|
||||
${YAZE_APP_EDITOR_SRC}
|
||||
${YAZE_APP_GFX_SRC}
|
||||
${YAZE_APP_ZELDA3_SRC}
|
||||
${YAZE_GUI_SRC}
|
||||
${IMGUI_SRC}
|
||||
|
||||
# Bundled Resources
|
||||
${YAZE_RESOURCE_FILES}
|
||||
)
|
||||
add_executable(
|
||||
yaze
|
||||
MACOSX_BUNDLE
|
||||
app/main.cc
|
||||
app/rom.cc
|
||||
${YAZE_APP_EMU_SRC}
|
||||
${YAZE_APP_CORE_SRC}
|
||||
${YAZE_APP_EDITOR_SRC}
|
||||
${YAZE_APP_GFX_SRC}
|
||||
${YAZE_APP_ZELDA3_SRC}
|
||||
${YAZE_GUI_SRC}
|
||||
${IMGUI_SRC}
|
||||
# Bundled Resources
|
||||
${YAZE_RESOURCE_FILES}
|
||||
)
|
||||
else()
|
||||
add_executable(
|
||||
yaze
|
||||
app/main.cc
|
||||
app/rom.cc
|
||||
${YAZE_APP_EMU_SRC}
|
||||
${YAZE_APP_CORE_SRC}
|
||||
${YAZE_APP_EDITOR_SRC}
|
||||
${YAZE_APP_GFX_SRC}
|
||||
${YAZE_APP_ZELDA3_SRC}
|
||||
${YAZE_GUI_SRC}
|
||||
${IMGUI_SRC}
|
||||
)
|
||||
add_executable(
|
||||
yaze
|
||||
app/main.cc
|
||||
app/rom.cc
|
||||
${YAZE_APP_EMU_SRC}
|
||||
${YAZE_APP_CORE_SRC}
|
||||
${YAZE_APP_EDITOR_SRC}
|
||||
${YAZE_APP_GFX_SRC}
|
||||
${YAZE_APP_ZELDA3_SRC}
|
||||
${YAZE_GUI_SRC}
|
||||
${IMGUI_SRC}
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(
|
||||
@@ -46,6 +45,7 @@ target_include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src/lib/imgui_test_engine
|
||||
${PNG_INCLUDE_DIRS}
|
||||
${SDL2_INCLUDE_DIR}
|
||||
${PROJECT_BINARY_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
@@ -63,11 +63,3 @@ if (APPLE)
|
||||
target_link_libraries(yaze PUBLIC ${COCOA_LIBRARY})
|
||||
endif()
|
||||
|
||||
if (WIN32 OR MINGW)
|
||||
target_link_libraries(
|
||||
yaze PUBLIC
|
||||
${CMAKE_SOURCE_DIR}/build/build-windows/bin/libpng16.dll
|
||||
zlib
|
||||
mingw32
|
||||
ws2_32)
|
||||
endif()
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
namespace {
|
||||
@@ -59,7 +59,6 @@ unsigned ldle(uint8_t const *const p_arr, unsigned const p_index) {
|
||||
|
||||
void stle(uint8_t *const p_arr, size_t const p_index, unsigned const p_val) {
|
||||
uint8_t v = (p_val >> (8 * p_index)) & 0xff;
|
||||
|
||||
p_arr[p_index] = v;
|
||||
}
|
||||
|
||||
@@ -91,30 +90,75 @@ uint32_t ldle2(uint8_t const *const p_arr) { return ldle(p_arr, 2); }
|
||||
// Helper function to get the third byte in a little endian number
|
||||
uint32_t ldle3(uint8_t const *const p_arr) { return ldle(p_arr, 3); }
|
||||
|
||||
void HandleHexStringParams(const std::string &hex,
|
||||
const HexStringParams ¶ms) {
|
||||
std::string result = hex;
|
||||
switch (params.prefix) {
|
||||
case HexStringParams::Prefix::kDollar:
|
||||
result = absl::StrCat("$", result);
|
||||
break;
|
||||
case HexStringParams::Prefix::kHash:
|
||||
result = absl::StrCat("#", result);
|
||||
break;
|
||||
case HexStringParams::Prefix::k0x:
|
||||
result = absl::StrCat("0x", result);
|
||||
case HexStringParams::Prefix::kNone:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string UppercaseHexByte(uint8_t byte, bool leading) {
|
||||
if (leading) {
|
||||
std::string result = absl::StrFormat("0x%02X", byte);
|
||||
return result;
|
||||
std::string HexByte(uint8_t byte, HexStringParams params) {
|
||||
std::string result;
|
||||
const static std::string kLowerFormat = "%02x";
|
||||
const static std::string kUpperFormat = "%02X";
|
||||
if (params.uppercase) {
|
||||
result = absl::StrFormat(kUpperFormat.c_str(), byte);
|
||||
} else {
|
||||
result = absl::StrFormat(kLowerFormat.c_str(), byte);
|
||||
}
|
||||
std::string result = absl::StrFormat("%02X", byte);
|
||||
HandleHexStringParams(result, params);
|
||||
return result;
|
||||
}
|
||||
std::string UppercaseHexWord(uint16_t word, bool leading) {
|
||||
if (leading) {
|
||||
std::string result = absl::StrFormat("0x%04X", word);
|
||||
return result;
|
||||
|
||||
std::string HexWord(uint16_t word, HexStringParams params) {
|
||||
std::string result;
|
||||
const static std::string kLowerFormat = "%04x";
|
||||
const static std::string kUpperFormat = "%04X";
|
||||
if (params.uppercase) {
|
||||
result = absl::StrFormat(kUpperFormat.c_str(), word);
|
||||
} else {
|
||||
result = absl::StrFormat(kLowerFormat.c_str(), word);
|
||||
}
|
||||
std::string result = absl::StrFormat("%04X", word);
|
||||
HandleHexStringParams(result, params);
|
||||
return result;
|
||||
}
|
||||
std::string UppercaseHexLong(uint32_t dword) {
|
||||
std::string result = absl::StrFormat("0x%06X", dword);
|
||||
|
||||
std::string HexLong(uint32_t dword, HexStringParams params) {
|
||||
std::string result;
|
||||
const static std::string kLowerFormat = "%06x";
|
||||
const static std::string kUpperFormat = "%06X";
|
||||
if (params.uppercase) {
|
||||
result = absl::StrFormat(kUpperFormat.c_str(), dword);
|
||||
} else {
|
||||
result = absl::StrFormat(kLowerFormat.c_str(), dword);
|
||||
}
|
||||
HandleHexStringParams(result, params);
|
||||
return result;
|
||||
}
|
||||
std::string UppercaseHexLongLong(uint64_t qword) {
|
||||
std::string result = absl::StrFormat("0x%08X", qword);
|
||||
|
||||
std::string HexLongLong(uint64_t qword, HexStringParams params) {
|
||||
std::string result;
|
||||
const static std::string kLowerFormat = "%08x";
|
||||
const static std::string kUpperFormat = "%08X";
|
||||
if (params.uppercase) {
|
||||
result = absl::StrFormat(kUpperFormat.c_str(), qword);
|
||||
} else {
|
||||
result = absl::StrFormat(kLowerFormat.c_str(), qword);
|
||||
}
|
||||
HandleHexStringParams(result, params);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -127,8 +171,6 @@ bool StringReplace(std::string &str, const std::string &from,
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<ExperimentFlags::Flags> ExperimentFlags::flags_;
|
||||
|
||||
uint32_t Get24LocalFromPC(uint8_t *data, int addr, bool pc) {
|
||||
uint32_t ret =
|
||||
(PcToSnes(addr) & 0xFF0000) | (data[addr + 1] << 8) | data[addr];
|
||||
@@ -317,17 +359,5 @@ void ApplyBpsPatch(const std::vector<uint8_t> &source,
|
||||
}
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> CheckVersion(const char *version) {
|
||||
std::string version_string = version;
|
||||
if (version_string != kYazeVersion) {
|
||||
std::string message =
|
||||
absl::StrFormat("Yaze version mismatch: expected %s, got %s",
|
||||
kYazeVersion.data(), version_string.c_str());
|
||||
return absl::InvalidArgumentError(message);
|
||||
}
|
||||
return version_string;
|
||||
}
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -7,23 +7,27 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
|
||||
/**
|
||||
* @namespace yaze::app::core
|
||||
* @namespace yaze::core
|
||||
* @brief Core application logic and utilities.
|
||||
*/
|
||||
namespace core {
|
||||
|
||||
std::string UppercaseHexByte(uint8_t byte, bool leading = false);
|
||||
std::string UppercaseHexWord(uint16_t word, bool leading = false);
|
||||
std::string UppercaseHexLong(uint32_t dword);
|
||||
std::string UppercaseHexLongLong(uint64_t qword);
|
||||
struct HexStringParams {
|
||||
enum class Prefix { kNone, kDollar, kHash, k0x } prefix = Prefix::kDollar;
|
||||
bool uppercase = true;
|
||||
};
|
||||
|
||||
std::string HexByte(uint8_t byte, HexStringParams params = {});
|
||||
std::string HexWord(uint16_t word, HexStringParams params = {});
|
||||
std::string HexLong(uint32_t dword, HexStringParams params = {});
|
||||
std::string HexLongLong(uint64_t qword, HexStringParams params = {});
|
||||
|
||||
bool StringReplace(std::string &str, const std::string &from,
|
||||
const std::string &to);
|
||||
@@ -33,16 +37,11 @@ bool StringReplace(std::string &str, const std::string &from,
|
||||
* @brief A class to manage experimental feature flags.
|
||||
*/
|
||||
class ExperimentFlags {
|
||||
public:
|
||||
public:
|
||||
struct Flags {
|
||||
// Log instructions to the GUI debugger.
|
||||
bool kLogInstructions = true;
|
||||
|
||||
// Flag to enable ImGui input config flags. Currently is
|
||||
// handled manually by controller class but should be
|
||||
// ported away from that eventually.
|
||||
bool kUseNewImGuiInput = false;
|
||||
|
||||
// Flag to enable the saving of all palettes to the Rom.
|
||||
bool kSaveAllPalettes = false;
|
||||
|
||||
@@ -97,60 +96,44 @@ public:
|
||||
} overworld;
|
||||
};
|
||||
|
||||
ExperimentFlags() = default;
|
||||
virtual ~ExperimentFlags() = default;
|
||||
auto flags() const {
|
||||
if (!flags_) {
|
||||
flags_ = std::make_shared<Flags>();
|
||||
}
|
||||
Flags *flags = flags_.get();
|
||||
return flags;
|
||||
}
|
||||
Flags *mutable_flags() {
|
||||
if (!flags_) {
|
||||
flags_ = std::make_shared<Flags>();
|
||||
}
|
||||
return flags_.get();
|
||||
static Flags &get() {
|
||||
static Flags instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::string Serialize() const {
|
||||
std::string result;
|
||||
result +=
|
||||
"kLogInstructions: " + std::to_string(flags_->kLogInstructions) + "\n";
|
||||
"kLogInstructions: " + std::to_string(get().kLogInstructions) + "\n";
|
||||
result +=
|
||||
"kUseNewImGuiInput: " + std::to_string(flags_->kUseNewImGuiInput) +
|
||||
"kSaveAllPalettes: " + std::to_string(get().kSaveAllPalettes) + "\n";
|
||||
result += "kSaveGfxGroups: " + std::to_string(get().kSaveGfxGroups) + "\n";
|
||||
result +=
|
||||
"kSaveWithChangeQueue: " + std::to_string(get().kSaveWithChangeQueue) +
|
||||
"\n";
|
||||
result +=
|
||||
"kSaveAllPalettes: " + std::to_string(flags_->kSaveAllPalettes) + "\n";
|
||||
result +=
|
||||
"kSaveGfxGroups: " + std::to_string(flags_->kSaveGfxGroups) + "\n";
|
||||
result += "kSaveWithChangeQueue: " +
|
||||
std::to_string(flags_->kSaveWithChangeQueue) + "\n";
|
||||
result += "kDrawDungeonRoomGraphics: " +
|
||||
std::to_string(flags_->kDrawDungeonRoomGraphics) + "\n";
|
||||
std::to_string(get().kDrawDungeonRoomGraphics) + "\n";
|
||||
result += "kNewFileDialogWrapper: " +
|
||||
std::to_string(flags_->kNewFileDialogWrapper) + "\n";
|
||||
std::to_string(get().kNewFileDialogWrapper) + "\n";
|
||||
result += "kLoadTexturesAsStreaming: " +
|
||||
std::to_string(flags_->kLoadTexturesAsStreaming) + "\n";
|
||||
std::to_string(get().kLoadTexturesAsStreaming) + "\n";
|
||||
result +=
|
||||
"kSaveDungeonMaps: " + std::to_string(flags_->kSaveDungeonMaps) + "\n";
|
||||
result += "kLogToConsole: " + std::to_string(flags_->kLogToConsole) + "\n";
|
||||
"kSaveDungeonMaps: " + std::to_string(get().kSaveDungeonMaps) + "\n";
|
||||
result += "kLogToConsole: " + std::to_string(get().kLogToConsole) + "\n";
|
||||
result += "kDrawOverworldSprites: " +
|
||||
std::to_string(flags_->overworld.kDrawOverworldSprites) + "\n";
|
||||
std::to_string(get().overworld.kDrawOverworldSprites) + "\n";
|
||||
result += "kSaveOverworldMaps: " +
|
||||
std::to_string(flags_->overworld.kSaveOverworldMaps) + "\n";
|
||||
std::to_string(get().overworld.kSaveOverworldMaps) + "\n";
|
||||
result += "kSaveOverworldEntrances: " +
|
||||
std::to_string(flags_->overworld.kSaveOverworldEntrances) + "\n";
|
||||
std::to_string(get().overworld.kSaveOverworldEntrances) + "\n";
|
||||
result += "kSaveOverworldExits: " +
|
||||
std::to_string(flags_->overworld.kSaveOverworldExits) + "\n";
|
||||
std::to_string(get().overworld.kSaveOverworldExits) + "\n";
|
||||
result += "kSaveOverworldItems: " +
|
||||
std::to_string(flags_->overworld.kSaveOverworldItems) + "\n";
|
||||
std::to_string(get().overworld.kSaveOverworldItems) + "\n";
|
||||
result += "kSaveOverworldProperties: " +
|
||||
std::to_string(flags_->overworld.kSaveOverworldProperties) + "\n";
|
||||
std::to_string(get().overworld.kSaveOverworldProperties) + "\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
static std::shared_ptr<Flags> flags_;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -158,8 +141,9 @@ private:
|
||||
* @brief A class to manage a value that can be modified and notify when it
|
||||
* changes.
|
||||
*/
|
||||
template <typename T> class NotifyValue {
|
||||
public:
|
||||
template <typename T>
|
||||
class NotifyValue {
|
||||
public:
|
||||
NotifyValue() : value_(), modified_(false), temp_value_() {}
|
||||
NotifyValue(const T &value)
|
||||
: value_(value), modified_(false), temp_value_() {}
|
||||
@@ -192,14 +176,14 @@ public:
|
||||
|
||||
bool modified() const { return modified_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
T value_;
|
||||
bool modified_;
|
||||
T temp_value_;
|
||||
};
|
||||
|
||||
static bool log_to_console = false;
|
||||
static std::string log_file_out = "log.txt";
|
||||
static const std::string kLogFileOut = "yaze_log.txt";
|
||||
|
||||
template <typename... Args>
|
||||
static void logf(const absl::FormatSpec<Args...> &format, const Args &...args) {
|
||||
@@ -207,39 +191,10 @@ static void logf(const absl::FormatSpec<Args...> &format, const Args &...args) {
|
||||
if (log_to_console) {
|
||||
std::cout << message << std::endl;
|
||||
}
|
||||
static std::ofstream fout(log_file_out, std::ios::out | std::ios::app);
|
||||
static std::ofstream fout(kLogFileOut, std::ios::out | std::ios::app);
|
||||
fout << message << std::endl;
|
||||
}
|
||||
|
||||
struct StructuredLog {
|
||||
std::string raw_message;
|
||||
std::string category;
|
||||
};
|
||||
|
||||
static absl::flat_hash_map<std::string, std::vector<std::string>> log_categories;
|
||||
|
||||
template <typename... Args>
|
||||
static void logm(const std::string &category,
|
||||
const absl::FormatSpec<Args...> &format, const Args &...args) {
|
||||
std::string message = absl::StrFormat(format, args...);
|
||||
if (log_to_console) {
|
||||
std::cout << category << ": " << message << std::endl;
|
||||
}
|
||||
if (log_categories.contains(category)) {
|
||||
log_categories[category].push_back(message);
|
||||
} else {
|
||||
log_categories[category] = {message};
|
||||
}
|
||||
}
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
static void log(std::string message) {
|
||||
static std::ofstream fout(log_file_out, std::ios::out | std::ios::app);
|
||||
fout << message << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr uint32_t kFastRomRegion = 0x808000;
|
||||
|
||||
inline uint32_t SnesToPc(uint32_t addr) noexcept {
|
||||
@@ -310,12 +265,7 @@ void ApplyBpsPatch(const std::vector<uint8_t> &source,
|
||||
const std::vector<uint8_t> &patch,
|
||||
std::vector<uint8_t> &target);
|
||||
|
||||
constexpr std::string_view kYazeVersion = "0.2.1";
|
||||
|
||||
absl::StatusOr<std::string> CheckVersion(const char *version);
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace core
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,40 +16,8 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr ImGuiWindowFlags kMainEditorFlags =
|
||||
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse |
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar |
|
||||
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoTitleBar;
|
||||
|
||||
using ImGui::Begin;
|
||||
using ImGui::End;
|
||||
using ImGui::GetIO;
|
||||
using ImGui::NewFrame;
|
||||
using ImGui::SetNextWindowPos;
|
||||
using ImGui::SetNextWindowSize;
|
||||
|
||||
void NewMasterFrame() {
|
||||
const ImGuiIO &io = GetIO();
|
||||
ImGui_ImplSDLRenderer2_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
NewFrame();
|
||||
SetNextWindowPos(gui::kZeroPos);
|
||||
ImVec2 dimensions(io.DisplaySize.x, io.DisplaySize.y);
|
||||
SetNextWindowSize(dimensions, ImGuiCond_Always);
|
||||
|
||||
if (!Begin("##YazeMain", nullptr, kMainEditorFlags)) {
|
||||
End();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
absl::Status Controller::OnEntry(std::string filename) {
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#if TARGET_IPHONE_SIMULATOR == 1 || TARGET_OS_IPHONE == 1
|
||||
@@ -68,7 +36,7 @@ absl::Status Controller::OnEntry(std::string filename) {
|
||||
RETURN_IF_ERROR(CreateRenderer())
|
||||
RETURN_IF_ERROR(CreateGuiContext())
|
||||
RETURN_IF_ERROR(LoadAudioDevice())
|
||||
editor_manager_.SetupScreen(filename);
|
||||
editor_manager_.Initialize(filename);
|
||||
active_ = true;
|
||||
return absl::OkStatus();
|
||||
}
|
||||
@@ -81,30 +49,30 @@ void Controller::OnInput() {
|
||||
while (SDL_PollEvent(&event)) {
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP: {
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
|
||||
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
|
||||
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
|
||||
io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP: {
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
|
||||
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
|
||||
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
|
||||
io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
|
||||
break;
|
||||
}
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_CLOSE:
|
||||
active_ = false;
|
||||
break;
|
||||
}
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_CLOSE:
|
||||
active_ = false;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
io.DisplaySize.x = static_cast<float>(event.window.data1);
|
||||
io.DisplaySize.y = static_cast<float>(event.window.data2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
io.DisplaySize.x = static_cast<float>(event.window.data1);
|
||||
io.DisplaySize.y = static_cast<float>(event.window.data2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,15 +93,26 @@ absl::Status Controller::OnLoad() {
|
||||
active_ = false;
|
||||
}
|
||||
#if TARGET_OS_IPHONE != 1
|
||||
if (platform_ != Platform::kiOS) {
|
||||
NewMasterFrame();
|
||||
constexpr ImGuiWindowFlags kMainEditorFlags =
|
||||
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse |
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar |
|
||||
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoTitleBar;
|
||||
|
||||
const ImGuiIO &io = ImGui::GetIO();
|
||||
ImGui_ImplSDLRenderer2_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
ImGui::SetNextWindowPos(gui::kZeroPos);
|
||||
ImVec2 dimensions(io.DisplaySize.x, io.DisplaySize.y);
|
||||
ImGui::SetNextWindowSize(dimensions, ImGuiCond_Always);
|
||||
|
||||
if (!ImGui::Begin("##YazeMain", nullptr, kMainEditorFlags)) {
|
||||
ImGui::End();
|
||||
}
|
||||
#endif
|
||||
RETURN_IF_ERROR(editor_manager_.Update());
|
||||
#if TARGET_OS_IPHONE != 1
|
||||
if (platform_ != Platform::kiOS) {
|
||||
End();
|
||||
}
|
||||
ImGui::End();
|
||||
#endif
|
||||
return absl::OkStatus();
|
||||
}
|
||||
@@ -162,9 +141,6 @@ void Controller::OnExit() {
|
||||
|
||||
absl::Status Controller::CreateWindow() {
|
||||
auto sdl_flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
|
||||
if (flags()->kUseNewImGuiInput) {
|
||||
sdl_flags |= SDL_INIT_GAMECONTROLLER;
|
||||
}
|
||||
|
||||
if (SDL_Init(sdl_flags) != 0) {
|
||||
return absl::InternalError(
|
||||
@@ -177,11 +153,11 @@ absl::Status Controller::CreateWindow() {
|
||||
int screen_height = display_mode.h * 0.8;
|
||||
|
||||
window_ = std::unique_ptr<SDL_Window, core::SDL_Deleter>(
|
||||
SDL_CreateWindow("Yet Another Zelda3 Editor", // window title
|
||||
SDL_WINDOWPOS_UNDEFINED, // initial x position
|
||||
SDL_WINDOWPOS_UNDEFINED, // initial y position
|
||||
screen_width, // width, in pixels
|
||||
screen_height, // height, in pixels
|
||||
SDL_CreateWindow("Yet Another Zelda3 Editor", // window title
|
||||
SDL_WINDOWPOS_UNDEFINED, // initial x position
|
||||
SDL_WINDOWPOS_UNDEFINED, // initial y position
|
||||
screen_width, // width, in pixels
|
||||
screen_height, // height, in pixels
|
||||
SDL_WINDOW_RESIZABLE),
|
||||
core::SDL_Deleter());
|
||||
if (window_ == nullptr) {
|
||||
@@ -202,9 +178,6 @@ absl::Status Controller::CreateGuiContext() {
|
||||
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
if (flags()->kUseNewImGuiInput) {
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
|
||||
}
|
||||
|
||||
// Initialize ImGui based on the backend
|
||||
ImGui_ImplSDL2_InitForSDLRenderer(window_.get(),
|
||||
@@ -235,7 +208,7 @@ absl::Status Controller::LoadAudioDevice() {
|
||||
want.format = AUDIO_S16;
|
||||
want.channels = 2;
|
||||
want.samples = 2048;
|
||||
want.callback = NULL; // Uses the queue
|
||||
want.callback = NULL; // Uses the queue
|
||||
audio_device_ = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
|
||||
if (audio_device_ == 0) {
|
||||
return absl::InternalError(
|
||||
@@ -277,6 +250,5 @@ absl::Status Controller::LoadConfigFiles() {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace core
|
||||
} // namespace yaze
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#include "absl/status/status.h"
|
||||
#include "app/core/platform/renderer.h"
|
||||
#include "app/core/utils/file_util.h"
|
||||
#include "app/editor/editor_manager.h"
|
||||
#include "app/editor/editor.h"
|
||||
#include "app/editor/editor_manager.h"
|
||||
#include "imgui/backends/imgui_impl_sdl2.h"
|
||||
#include "imgui/backends/imgui_impl_sdlrenderer2.h"
|
||||
#include "imgui/imconfig.h"
|
||||
@@ -18,7 +18,6 @@
|
||||
int main(int argc, char **argv);
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
/**
|
||||
@@ -45,7 +44,7 @@ class Controller : public ExperimentFlags {
|
||||
absl::Status LoadConfigFiles();
|
||||
|
||||
void SetupScreen(std::string filename = "") {
|
||||
editor_manager_.SetupScreen(filename);
|
||||
editor_manager_.Initialize(filename);
|
||||
}
|
||||
auto editor_manager() -> editor::EditorManager & { return editor_manager_; }
|
||||
auto renderer() -> SDL_Renderer * {
|
||||
@@ -54,13 +53,14 @@ class Controller : public ExperimentFlags {
|
||||
auto window() -> SDL_Window * { return window_.get(); }
|
||||
void init_test_editor(editor::Editor *editor) { test_editor_ = editor; }
|
||||
void set_active(bool active) { active_ = active; }
|
||||
auto active() { return active_; }
|
||||
|
||||
private:
|
||||
friend int ::main(int argc, char **argv);
|
||||
|
||||
bool active_;
|
||||
bool active_ = false;
|
||||
Platform platform_;
|
||||
editor::Editor *test_editor_;
|
||||
editor::Editor *test_editor_ = nullptr;
|
||||
editor::EditorManager editor_manager_;
|
||||
|
||||
int audio_frequency_ = 48000;
|
||||
@@ -70,7 +70,6 @@ class Controller : public ExperimentFlags {
|
||||
};
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_CORE_CONTROLLER_H
|
||||
|
||||
@@ -206,8 +206,8 @@
|
||||
}
|
||||
|
||||
- (void)openFileAction:(id)sender {
|
||||
if (!yaze::app::SharedRom::shared_rom_
|
||||
->LoadFromFile(yaze::app::core::FileDialogWrapper::ShowOpenFileDialog())
|
||||
if (!yaze::SharedRom::shared_rom_
|
||||
->LoadFromFile(yaze::core::FileDialogWrapper::ShowOpenFileDialog())
|
||||
.ok()) {
|
||||
NSAlert *alert = [[NSAlert alloc] init];
|
||||
[alert setMessageText:@"Error"];
|
||||
@@ -238,7 +238,7 @@ extern "C" void yaze_initialize_cococa() {
|
||||
|
||||
extern "C" void yaze_run_cocoa_app_delegate(const char *filename) {
|
||||
yaze_initialize_cococa();
|
||||
yaze::app::core::Controller controller;
|
||||
yaze::core::Controller controller;
|
||||
RETURN_VOID_IF_ERROR(controller.OnEntry(filename));
|
||||
while (controller.IsActive()) {
|
||||
@autoreleasepool {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <vector>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
void CopyImageToClipboard(const std::vector<uint8_t>& data) {}
|
||||
@@ -12,5 +11,4 @@ void GetImageFromClipboard(std::vector<uint8_t>& data, int& width,
|
||||
int& height) {}
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
@@ -5,14 +5,12 @@
|
||||
#include <vector>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
void CopyImageToClipboard(const std::vector<uint8_t> &data);
|
||||
void GetImageFromClipboard(std::vector<uint8_t> &data, int &width, int &height);
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_CORE_PLATFORM_CLIPBOARD_H
|
||||
@@ -6,7 +6,7 @@
|
||||
#ifdef TARGET_OS_MAC
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
void yaze::app::core::CopyImageToClipboard(const std::vector<uint8_t>& pngData) {
|
||||
void yaze::core::CopyImageToClipboard(const std::vector<uint8_t>& pngData) {
|
||||
NSData* data = [NSData dataWithBytes:pngData.data() length:pngData.size()];
|
||||
NSImage* image = [[NSImage alloc] initWithData:data];
|
||||
|
||||
@@ -15,7 +15,7 @@ void yaze::app::core::CopyImageToClipboard(const std::vector<uint8_t>& pngData)
|
||||
[pasteboard writeObjects:@[ image ]];
|
||||
}
|
||||
|
||||
void yaze::app::core::GetImageFromClipboard(std::vector<uint8_t>& pixel_data, int& width, int& height) {
|
||||
void yaze::core::GetImageFromClipboard(std::vector<uint8_t>& pixel_data, int& width, int& height) {
|
||||
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
|
||||
NSArray* classArray = [NSArray arrayWithObject:[NSImage class]];
|
||||
NSDictionary* options = [NSDictionary dictionary];
|
||||
|
||||
@@ -7,12 +7,11 @@
|
||||
#endif // _WIN32
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
std::string FileDialogWrapper::ShowOpenFileDialog() {
|
||||
std::string FileDialogWrapper::ShowOpenFileDialog() {
|
||||
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||
|
||||
IFileDialog *pfd = NULL;
|
||||
@@ -44,7 +43,7 @@ namespace core {
|
||||
return file_path_windows;
|
||||
}
|
||||
|
||||
std::string FileDialogWrapper::ShowOpenFolderDialog() {
|
||||
std::string FileDialogWrapper::ShowOpenFolderDialog() {
|
||||
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||
|
||||
IFileDialog *pfd = NULL;
|
||||
@@ -141,5 +140,4 @@ std::vector<std::string> FileDialogWrapper::GetFilesInFolder(
|
||||
#endif
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <vector>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
class FileDialogWrapper {
|
||||
@@ -28,7 +27,6 @@ class FileDialogWrapper {
|
||||
};
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_CORE_PLATFORM_FILE_DIALOG_H
|
||||
|
||||
@@ -37,20 +37,18 @@ std::string ShowOpenFileDialogSync() {
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::string yaze::app::core::FileDialogWrapper::ShowOpenFileDialog() {
|
||||
return ShowOpenFileDialogSync();
|
||||
}
|
||||
std::string yaze::core::FileDialogWrapper::ShowOpenFileDialog() { return ShowOpenFileDialogSync(); }
|
||||
|
||||
std::string yaze::app::core::FileDialogWrapper::ShowOpenFolderDialog() { return ""; }
|
||||
std::string yaze::core::FileDialogWrapper::ShowOpenFolderDialog() { return ""; }
|
||||
|
||||
std::vector<std::string> yaze::app::core::FileDialogWrapper::GetFilesInFolder(
|
||||
std::vector<std::string> yaze::core::FileDialogWrapper::GetFilesInFolder(
|
||||
const std::string &folder) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::string> yaze::app::core::FileDialogWrapper::GetSubdirectoriesInFolder(
|
||||
std::vector<std::string> yaze::core::FileDialogWrapper::GetSubdirectoriesInFolder(
|
||||
const std::string &folder) {
|
||||
return {};
|
||||
}
|
||||
@@ -60,7 +58,7 @@ std::vector<std::string> yaze::app::core::FileDialogWrapper::GetSubdirectoriesIn
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
std::string yaze::app::core::FileDialogWrapper::ShowOpenFileDialog() {
|
||||
std::string yaze::core::FileDialogWrapper::ShowOpenFileDialog() {
|
||||
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
|
||||
[openPanel setCanChooseFiles:YES];
|
||||
[openPanel setCanChooseDirectories:NO];
|
||||
@@ -75,7 +73,7 @@ std::string yaze::app::core::FileDialogWrapper::ShowOpenFileDialog() {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string yaze::app::core::FileDialogWrapper::ShowOpenFolderDialog() {
|
||||
std::string yaze::core::FileDialogWrapper::ShowOpenFolderDialog() {
|
||||
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
|
||||
[openPanel setCanChooseFiles:NO];
|
||||
[openPanel setCanChooseDirectories:YES];
|
||||
@@ -90,7 +88,7 @@ std::string yaze::app::core::FileDialogWrapper::ShowOpenFolderDialog() {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::vector<std::string> yaze::app::core::FileDialogWrapper::GetFilesInFolder(
|
||||
std::vector<std::string> yaze::core::FileDialogWrapper::GetFilesInFolder(
|
||||
const std::string& folder) {
|
||||
std::vector<std::string> filenames;
|
||||
NSFileManager* fileManager = [NSFileManager defaultManager];
|
||||
@@ -106,7 +104,7 @@ std::vector<std::string> yaze::app::core::FileDialogWrapper::GetFilesInFolder(
|
||||
return filenames;
|
||||
}
|
||||
|
||||
std::vector<std::string> yaze::app::core::FileDialogWrapper::GetSubdirectoriesInFolder(
|
||||
std::vector<std::string> yaze::core::FileDialogWrapper::GetSubdirectoriesInFolder(
|
||||
const std::string& folder) {
|
||||
std::vector<std::string> subdirectories;
|
||||
NSFileManager* fileManager = [NSFileManager defaultManager];
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <string>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
/**
|
||||
@@ -14,7 +13,6 @@ namespace core {
|
||||
std::string GetBundleResourcePath();
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_CORE_PLATFORM_FILE_PATH_H
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR == 1 || TARGET_OS_IPHONE == 1
|
||||
std::string yaze::app::core::GetBundleResourcePath() {
|
||||
std::string yaze::core::GetBundleResourcePath() {
|
||||
NSBundle* bundle = [NSBundle mainBundle];
|
||||
NSString* resourceDirectoryPath = [bundle bundlePath];
|
||||
NSString* path = [resourceDirectoryPath stringByAppendingString:@"/"];
|
||||
return [path UTF8String];
|
||||
}
|
||||
#elif TARGET_OS_MAC == 1
|
||||
std::string yaze::app::core::GetBundleResourcePath() {
|
||||
std::string yaze::core::GetBundleResourcePath() {
|
||||
NSBundle* bundle = [NSBundle mainBundle];
|
||||
NSString* resourceDirectoryPath = [bundle bundlePath];
|
||||
NSString* path = [resourceDirectoryPath stringByAppendingString:@"/"];
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include "app/core/platform/font_loader.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
absl::Status LoadPackageFonts() {
|
||||
@@ -63,7 +62,8 @@ absl::Status LoadPackageFonts() {
|
||||
"Contents/Resources/font/", font_path);
|
||||
#endif
|
||||
#else
|
||||
actual_font_path = std::filesystem::absolute(font_path).string();
|
||||
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)) {
|
||||
@@ -86,8 +86,11 @@ absl::Status LoadPackageFonts() {
|
||||
#else
|
||||
actual_icon_font_path = std::filesystem::absolute(icon_font_path).string();
|
||||
#endif
|
||||
io.Fonts->AddFontFromFileTTF(actual_icon_font_path.data(), ICON_FONT_SIZE,
|
||||
&icons_config, icons_ranges);
|
||||
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
|
||||
std::string actual_japanese_font_path = "";
|
||||
@@ -102,8 +105,9 @@ absl::Status LoadPackageFonts() {
|
||||
japanese_font_path);
|
||||
#endif
|
||||
#else
|
||||
actual_japanese_font_path = absl::StrCat("assets/font/", japanese_font_path);
|
||||
actual_japanese_font_path =
|
||||
std::filesystem::absolute(japanese_font_path).string();
|
||||
std::filesystem::absolute(actual_japanese_font_path).string();
|
||||
#endif
|
||||
io.Fonts->AddFontFromFileTTF(actual_japanese_font_path.data(), 18.0f,
|
||||
&japanese_font_config,
|
||||
@@ -237,5 +241,4 @@ void LoadSystemFonts() {
|
||||
#endif
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
@@ -4,14 +4,12 @@
|
||||
#include "absl/status/status.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
void LoadSystemFonts();
|
||||
absl::Status LoadPackageFonts();
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_CORE_PLATFORM_FONTLOADER_H
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
#if TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1
|
||||
/* iOS */
|
||||
void yaze::app::core::LoadSystemFonts() {}
|
||||
void yaze::core::LoadSystemFonts() {}
|
||||
|
||||
#elif TARGET_OS_MAC == 1
|
||||
/* macOS */
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
void yaze::app::core::LoadSystemFonts() {
|
||||
void yaze::core::LoadSystemFonts() {
|
||||
NSArray *fontNames = @[ @"Helvetica", @"Times New Roman", @"Courier", @"Arial", @"Verdana" ];
|
||||
|
||||
for (NSString *fontName in fontNames) {
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "app/gfx/bitmap.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
/**
|
||||
@@ -77,7 +76,6 @@ class Renderer {
|
||||
};
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
@end
|
||||
#else
|
||||
@interface AppViewController : UIViewController <MTKViewDelegate>
|
||||
@property(nonatomic) yaze::app::core::Controller *controller;
|
||||
@property(nonatomic) yaze::core::Controller *controller;
|
||||
@property(nonatomic) UIHoverGestureRecognizer *hoverGestureRecognizer;
|
||||
@property(nonatomic) UIPinchGestureRecognizer *pinchRecognizer;
|
||||
@property(nonatomic) UISwipeGestureRecognizer *swipeRecognizer;
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "imgui/misc/cpp/imgui_stdlib.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
|
||||
absl::Status Project::Open(const std::string& project_path) {
|
||||
filepath = project_path;
|
||||
@@ -185,5 +184,5 @@ std::string ResourceLabelManager::CreateOrGetLabel(
|
||||
return labels_[type][key];
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
} // namespace yaze
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "app/core/utils/file_util.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
|
||||
const std::string kRecentFilesFilename = "recent_files.txt";
|
||||
constexpr char kEndOfProjectFile[] = "EndOfProjectFile";
|
||||
@@ -25,7 +24,7 @@ constexpr char kEndOfProjectFile[] = "EndOfProjectFile";
|
||||
* user can have different rom file names for a single project and keep track of
|
||||
* backups.
|
||||
*/
|
||||
struct Project : public core::ExperimentFlags {
|
||||
struct Project {
|
||||
absl::Status Create(const std::string& project_name) {
|
||||
name = project_name;
|
||||
project_opened_ = true;
|
||||
@@ -130,7 +129,7 @@ class RecentFilesManager {
|
||||
std::vector<std::string> recent_files_;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_CORE_PROJECT_H
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <sstream>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
std::string GetFileExtension(const std::string &filename) {
|
||||
@@ -30,8 +29,31 @@ std::string GetFileName(const std::string &filename) {
|
||||
return filename.substr(slash + 1);
|
||||
}
|
||||
|
||||
std::string LoadFile(const std::string &filename, Platform platform) {
|
||||
std::string LoadFile(const std::string &filename) {
|
||||
std::string contents;
|
||||
std::ifstream file(filename);
|
||||
if (file.is_open()) {
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
contents = buffer.str();
|
||||
file.close();
|
||||
} else {
|
||||
// Throw an exception
|
||||
throw std::runtime_error("Could not open file: " + filename);
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::string LoadConfigFile(const std::string &filename) {
|
||||
std::string contents;
|
||||
Platform platform;
|
||||
#if defined(_WIN32)
|
||||
platform = Platform::kWindows;
|
||||
#elif defined(__APPLE__)
|
||||
platform = Platform::kMacOS;
|
||||
#else
|
||||
platform = Platform::kLinux;
|
||||
#endif
|
||||
std::string filepath = GetConfigDirectory(platform) + "/" + filename;
|
||||
std::ifstream file(filepath);
|
||||
if (file.is_open()) {
|
||||
@@ -56,19 +78,18 @@ void SaveFile(const std::string &filename, const std::string &contents,
|
||||
std::string GetConfigDirectory(Platform platform) {
|
||||
std::string config_directory = ".yaze";
|
||||
switch (platform) {
|
||||
case Platform::kWindows:
|
||||
config_directory = "~/AppData/Roaming/yaze";
|
||||
break;
|
||||
case Platform::kMacOS:
|
||||
case Platform::kLinux:
|
||||
config_directory = "~/.config/yaze";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case Platform::kWindows:
|
||||
config_directory = "~/AppData/Roaming/yaze";
|
||||
break;
|
||||
case Platform::kMacOS:
|
||||
case Platform::kLinux:
|
||||
config_directory = "~/.config/yaze";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return config_directory;
|
||||
}
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace core
|
||||
} // namespace yaze
|
||||
|
||||
@@ -4,21 +4,20 @@
|
||||
#include <string>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
enum class Platform { kUnknown, kMacOS, kiOS, kWindows, kLinux };
|
||||
|
||||
std::string GetFileExtension(const std::string &filename);
|
||||
std::string GetFileName(const std::string &filename);
|
||||
std::string LoadFile(const std::string &filename, Platform platform);
|
||||
std::string LoadFile(const std::string &filename);
|
||||
std::string LoadConfigFile(const std::string &filename);
|
||||
std::string GetConfigDirectory(Platform platform);
|
||||
|
||||
void SaveFile(const std::string &filename, const std::string &data,
|
||||
Platform platform);
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace core
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_CORE_UTILS_FILE_UTIL_H
|
||||
#endif // YAZE_APP_CORE_UTILS_FILE_UTIL_H
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <SDL.h>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace core {
|
||||
|
||||
/**
|
||||
@@ -19,22 +18,17 @@ struct SDL_Deleter {
|
||||
* @brief Deleter for SDL_Texture.
|
||||
*/
|
||||
struct SDL_Texture_Deleter {
|
||||
void operator()(SDL_Texture *p) const {
|
||||
SDL_DestroyTexture(p);
|
||||
}
|
||||
void operator()(SDL_Texture *p) const { SDL_DestroyTexture(p); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Deleter for SDL_Surface.
|
||||
*/
|
||||
struct SDL_Surface_Deleter {
|
||||
void operator()(SDL_Surface *p) const {
|
||||
SDL_FreeSurface(p);
|
||||
}
|
||||
void operator()(SDL_Surface *p) const { SDL_FreeSurface(p); }
|
||||
};
|
||||
|
||||
} // namespace core
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_CORE_UTILS_SDL_DELETER_H_
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
#include "assembly_editor.h"
|
||||
|
||||
#include "ImGuiColorTextEdit/TextEditor.h"
|
||||
#include "ImGuiFileDialog/ImGuiFileDialog.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "app/core/platform/file_dialog.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/modules/text_editor.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using core::FileDialogWrapper;
|
||||
@@ -278,21 +276,14 @@ void AssemblyEditor::DrawFileTabView() {
|
||||
void AssemblyEditor::DrawFileMenu() {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
if (ImGui::MenuItem("Open", "Ctrl+O")) {
|
||||
ImGuiFileDialog::Instance()->OpenDialog(
|
||||
"ChooseASMFileDlg", "Open ASM file", ".asm,.txt", ".");
|
||||
auto filename = core::FileDialogWrapper::ShowOpenFileDialog();
|
||||
ChangeActiveFile(filename);
|
||||
}
|
||||
if (ImGui::MenuItem("Save", "Ctrl+S")) {
|
||||
// TODO: Implement this
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGuiFileDialog::Instance()->Display("ChooseASMFileDlg")) {
|
||||
if (ImGuiFileDialog::Instance()->IsOk()) {
|
||||
ChangeActiveFile(ImGuiFileDialog::Instance()->GetFilePathName());
|
||||
}
|
||||
ImGuiFileDialog::Instance()->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void AssemblyEditor::DrawEditMenu() {
|
||||
@@ -364,5 +355,4 @@ absl::Status AssemblyEditor::Redo() {
|
||||
absl::Status AssemblyEditor::Update() { return absl::OkStatus(); }
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ImGuiColorTextEdit/TextEditor.h"
|
||||
#include "app/core/common.h"
|
||||
#include "app/editor/editor.h"
|
||||
#include "app/gui/modules/text_editor.h"
|
||||
#include "app/gui/style.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
/**
|
||||
@@ -69,7 +68,6 @@ class AssemblyEditor : public Editor {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "imgui_memory_editor.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using ImGui::SameLine;
|
||||
@@ -78,7 +77,6 @@ struct MemoryEditorWithDiffChecker : public SharedRom {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_CODE_MEMORY_EDITOR_H
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/dungeon/object_names.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui_memory_editor.h"
|
||||
#include "zelda3/dungeon/room.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using core::Renderer;
|
||||
@@ -72,11 +72,12 @@ absl::Status DungeonEditor::Update() {
|
||||
|
||||
absl::Status DungeonEditor::Initialize() {
|
||||
auto dungeon_man_pal_group = rom()->palette_group().dungeon_main;
|
||||
|
||||
for (int i = 0; i < 0x100 + 40; i++) {
|
||||
rooms_.emplace_back(zelda3::dungeon::Room(/*room_id=*/i));
|
||||
rooms_.emplace_back(zelda3::Room(/*room_id=*/i));
|
||||
rooms_[i].LoadHeader();
|
||||
rooms_[i].LoadRoomFromROM();
|
||||
if (flags()->kDrawDungeonRoomGraphics) {
|
||||
if (core::ExperimentFlags::get().kDrawDungeonRoomGraphics) {
|
||||
rooms_[i].LoadRoomGraphics();
|
||||
}
|
||||
|
||||
@@ -96,11 +97,11 @@ absl::Status DungeonEditor::Initialize() {
|
||||
LoadDungeonRoomSize();
|
||||
// LoadRoomEntrances
|
||||
for (int i = 0; i < 0x07; ++i) {
|
||||
entrances_.emplace_back(zelda3::dungeon::RoomEntrance(*rom(), i, true));
|
||||
entrances_.emplace_back(zelda3::RoomEntrance(*rom(), i, true));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 0x85; ++i) {
|
||||
entrances_.emplace_back(zelda3::dungeon::RoomEntrance(*rom(), i, false));
|
||||
entrances_.emplace_back(zelda3::RoomEntrance(*rom(), i, false));
|
||||
}
|
||||
|
||||
// Load the palette group and palette for the dungeon
|
||||
@@ -117,31 +118,36 @@ absl::Status DungeonEditor::Initialize() {
|
||||
}
|
||||
|
||||
absl::Status DungeonEditor::RefreshGraphics() {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int block = rooms_[current_room_id_].blocks()[i];
|
||||
RETURN_IF_ERROR(graphics_bin_[block].ApplyPaletteWithTransparent(
|
||||
current_palette_group_[current_palette_id_], 0));
|
||||
Renderer::GetInstance().UpdateBitmap(&graphics_bin_[block]);
|
||||
}
|
||||
std::for_each_n(
|
||||
rooms_[current_room_id_].blocks().begin(), 8,
|
||||
[this](int block) -> absl::Status {
|
||||
RETURN_IF_ERROR(graphics_bin_[block].ApplyPaletteWithTransparent(
|
||||
current_palette_group_[current_palette_id_], 0));
|
||||
Renderer::GetInstance().UpdateBitmap(&graphics_bin_[block]);
|
||||
return absl::OkStatus();
|
||||
});
|
||||
|
||||
auto sprites_aux1_pal_group = rom()->palette_group().sprites_aux1;
|
||||
for (int i = 9; i < 16; i++) {
|
||||
int block = rooms_[current_room_id_].blocks()[i];
|
||||
RETURN_IF_ERROR(graphics_bin_[block].ApplyPaletteWithTransparent(
|
||||
sprites_aux1_pal_group[current_palette_id_], 0));
|
||||
Renderer::GetInstance().UpdateBitmap(&graphics_bin_[block]);
|
||||
}
|
||||
std::for_each_n(
|
||||
rooms_[current_room_id_].blocks().begin() + 8, 8,
|
||||
[this, &sprites_aux1_pal_group](int block) -> absl::Status {
|
||||
RETURN_IF_ERROR(graphics_bin_[block].ApplyPaletteWithTransparent(
|
||||
sprites_aux1_pal_group[current_palette_id_], 0));
|
||||
Renderer::GetInstance().UpdateBitmap(&graphics_bin_[block]);
|
||||
return absl::OkStatus();
|
||||
});
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void DungeonEditor::LoadDungeonRoomSize() {
|
||||
std::map<int, std::vector<int>> rooms_by_bank;
|
||||
for (const auto& room : room_size_addresses_) {
|
||||
for (const auto &room : room_size_addresses_) {
|
||||
int bank = room.second >> 16;
|
||||
rooms_by_bank[bank].push_back(room.second);
|
||||
}
|
||||
|
||||
// Process and calculate room sizes within each bank
|
||||
for (auto& bank_rooms : rooms_by_bank) {
|
||||
for (auto &bank_rooms : rooms_by_bank) {
|
||||
// Sort the rooms within this bank
|
||||
std::sort(bank_rooms.second.begin(), bank_rooms.second.end());
|
||||
|
||||
@@ -151,7 +157,7 @@ void DungeonEditor::LoadDungeonRoomSize() {
|
||||
// Identify the room ID for the current room pointer
|
||||
int room_id =
|
||||
std::find_if(room_size_addresses_.begin(), room_size_addresses_.end(),
|
||||
[room_ptr](const auto& entry) {
|
||||
[room_ptr](const auto &entry) {
|
||||
return entry.second == room_ptr;
|
||||
})
|
||||
->first;
|
||||
@@ -315,14 +321,14 @@ void DungeonEditor::DrawRoomSelector() {
|
||||
gui::InputHexWord("Room ID", ¤t_room_id_);
|
||||
gui::InputHex("Palette ID", ¤t_palette_id_);
|
||||
|
||||
if (ImGuiID child_id = ImGui::GetID((void*)(intptr_t)9);
|
||||
if (ImGuiID child_id = ImGui::GetID((void *)(intptr_t)9);
|
||||
BeginChild(child_id, ImGui::GetContentRegionAvail(), true,
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
|
||||
int i = 0;
|
||||
for (const auto each_room_name : zelda3::dungeon::kRoomNames) {
|
||||
for (const auto each_room_name : zelda3::kRoomNames) {
|
||||
rom()->resource_label()->SelectableLabelWithNameEdit(
|
||||
current_room_id_ == i, "Dungeon Room Names",
|
||||
core::UppercaseHexByte(i), each_room_name.data());
|
||||
core::HexByte(i), each_room_name.data());
|
||||
if (ImGui::IsItemClicked()) {
|
||||
// TODO: Jump to tab if room is already open
|
||||
current_room_id_ = i;
|
||||
@@ -396,8 +402,8 @@ void DungeonEditor::DrawEntranceSelector() {
|
||||
for (int i = 0; i < 0x85 + 7; i++) {
|
||||
rom()->resource_label()->SelectableLabelWithNameEdit(
|
||||
current_entrance_id_ == i, "Dungeon Entrance Names",
|
||||
core::UppercaseHexByte(i),
|
||||
zelda3::dungeon::kEntranceNames[i].data());
|
||||
core::HexByte(i),
|
||||
zelda3::kEntranceNames[i].data());
|
||||
|
||||
if (ImGui::IsItemClicked()) {
|
||||
current_entrance_id_ = i;
|
||||
@@ -428,12 +434,12 @@ void DungeonEditor::DrawDungeonTabView() {
|
||||
for (int n = 0; n < active_rooms_.Size;) {
|
||||
bool open = true;
|
||||
|
||||
if (active_rooms_[n] > sizeof(zelda3::dungeon::kRoomNames) / 4) {
|
||||
if (active_rooms_[n] > sizeof(zelda3::kRoomNames) / 4) {
|
||||
active_rooms_.erase(active_rooms_.Data + n);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BeginTabItem(zelda3::dungeon::kRoomNames[active_rooms_[n]].data(),
|
||||
if (BeginTabItem(zelda3::kRoomNames[active_rooms_[n]].data(),
|
||||
&open, ImGuiTabItemFlags_None)) {
|
||||
DrawDungeonCanvas(active_rooms_[n]);
|
||||
EndTabItem();
|
||||
@@ -514,7 +520,7 @@ void DungeonEditor::DrawRoomGraphics() {
|
||||
void DungeonEditor::DrawTileSelector() {
|
||||
if (BeginTabBar("##TabBar", ImGuiTabBarFlags_FittingPolicyScroll)) {
|
||||
if (BeginTabItem("Room Graphics")) {
|
||||
if (ImGuiID child_id = ImGui::GetID((void*)(intptr_t)3);
|
||||
if (ImGuiID child_id = ImGui::GetID((void *)(intptr_t)3);
|
||||
BeginChild(child_id, ImGui::GetContentRegionAvail(), true,
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
|
||||
DrawRoomGraphics();
|
||||
@@ -543,7 +549,7 @@ void DungeonEditor::DrawObjectRenderer() {
|
||||
|
||||
int selected_object = 0;
|
||||
int i = 0;
|
||||
for (const auto object_name : zelda3::dungeon::Type1RoomObjectNames) {
|
||||
for (const auto object_name : zelda3::Type1RoomObjectNames) {
|
||||
if (ImGui::Selectable(object_name.data(), selected_object == i)) {
|
||||
selected_object = i;
|
||||
current_object_ = i;
|
||||
@@ -577,7 +583,7 @@ void DungeonEditor::DrawObjectRenderer() {
|
||||
if (object_loaded_) {
|
||||
ImGui::Begin("Memory Viewer", &object_loaded_, 0);
|
||||
static MemoryEditor mem_edit;
|
||||
mem_edit.DrawContents((void*)object_renderer_.mutable_memory(),
|
||||
mem_edit.DrawContents((void *)object_renderer_.mutable_memory(),
|
||||
object_renderer_.mutable_memory()->size());
|
||||
ImGui::End();
|
||||
}
|
||||
@@ -586,7 +592,7 @@ void DungeonEditor::DrawObjectRenderer() {
|
||||
// ============================================================================
|
||||
|
||||
void DungeonEditor::CalculateUsageStats() {
|
||||
for (const auto& room : rooms_) {
|
||||
for (const auto &room : rooms_) {
|
||||
if (blockset_usage_.find(room.blockset) == blockset_usage_.end()) {
|
||||
blockset_usage_[room.blockset] = 1;
|
||||
} else {
|
||||
@@ -608,15 +614,15 @@ void DungeonEditor::CalculateUsageStats() {
|
||||
}
|
||||
|
||||
void DungeonEditor::RenderSetUsage(
|
||||
const absl::flat_hash_map<uint16_t, int>& usage_map, uint16_t& selected_set,
|
||||
const absl::flat_hash_map<uint16_t, int> &usage_map, uint16_t &selected_set,
|
||||
int spriteset_offset) {
|
||||
// Sort the usage map by set number
|
||||
std::vector<std::pair<uint16_t, int>> sorted_usage(usage_map.begin(),
|
||||
usage_map.end());
|
||||
std::sort(sorted_usage.begin(), sorted_usage.end(),
|
||||
[](const auto& a, const auto& b) { return a.first < b.first; });
|
||||
[](const auto &a, const auto &b) { return a.first < b.first; });
|
||||
|
||||
for (const auto& [set, count] : sorted_usage) {
|
||||
for (const auto &[set, count] : sorted_usage) {
|
||||
std::string display_str;
|
||||
if (spriteset_offset != 0x00) {
|
||||
display_str = absl::StrFormat("%#02x, %#02x: %d", set,
|
||||
@@ -637,7 +643,7 @@ namespace {
|
||||
// Range for spritesets 0-0x8F
|
||||
// Range for palettes 0-0x47
|
||||
template <typename T>
|
||||
void RenderUnusedSets(const absl::flat_hash_map<T, int>& usage_map, int max_set,
|
||||
void RenderUnusedSets(const absl::flat_hash_map<T, int> &usage_map, int max_set,
|
||||
int spriteset_offset = 0x00) {
|
||||
std::vector<int> unused_sets;
|
||||
for (int i = 0; i < max_set; i++) {
|
||||
@@ -645,7 +651,7 @@ void RenderUnusedSets(const absl::flat_hash_map<T, int>& usage_map, int max_set,
|
||||
unused_sets.push_back(i);
|
||||
}
|
||||
}
|
||||
for (const auto& set : unused_sets) {
|
||||
for (const auto &set : unused_sets) {
|
||||
if (spriteset_offset != 0x00) {
|
||||
Text("%#02x, %#02x", set, (set + spriteset_offset));
|
||||
} else {
|
||||
@@ -755,7 +761,7 @@ void DungeonEditor::DrawUsageGrid() {
|
||||
break;
|
||||
}
|
||||
// Determine if this square should be highlighted
|
||||
const auto& room = rooms_[row * squaresWide + col];
|
||||
const auto &room = rooms_[row * squaresWide + col];
|
||||
|
||||
// Create a button or selectable for each square
|
||||
ImGui::BeginGroup();
|
||||
@@ -828,5 +834,4 @@ void DungeonEditor::DrawUsageGrid() {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#ifndef YAZE_APP_EDITOR_DUNGEONEDITOR_H
|
||||
#define YAZE_APP_EDITOR_DUNGEONEDITOR_H
|
||||
|
||||
#include "app/core/common.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "app/core/common.h"
|
||||
#include "app/editor/editor.h"
|
||||
#include "app/editor/graphics/gfx_group_editor.h"
|
||||
#include "app/editor/graphics/palette_editor.h"
|
||||
#include "app/editor/editor.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/rom.h"
|
||||
#include "imgui/imgui.h"
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "zelda3/dungeon/room_object.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
constexpr ImGuiTabItemFlags kDungeonTabFlags =
|
||||
@@ -40,9 +39,7 @@ constexpr ImGuiTableFlags kDungeonTableFlags =
|
||||
* tile selector, and object renderer. Additionally, it handles loading room
|
||||
* entrances, calculating usage statistics, and rendering set usage.
|
||||
*/
|
||||
class DungeonEditor : public Editor,
|
||||
public SharedRom,
|
||||
public core::ExperimentFlags {
|
||||
class DungeonEditor : public Editor, public SharedRom {
|
||||
public:
|
||||
DungeonEditor() { type_ = EditorType::kDungeon; }
|
||||
|
||||
@@ -120,9 +117,9 @@ class DungeonEditor : public Editor,
|
||||
std::array<gfx::Bitmap, kNumGfxSheets> graphics_bin_;
|
||||
|
||||
std::vector<gfx::Bitmap*> room_gfx_sheets_;
|
||||
std::vector<zelda3::dungeon::Room> rooms_;
|
||||
std::vector<zelda3::dungeon::RoomEntrance> entrances_;
|
||||
zelda3::dungeon::DungeonObjectRenderer object_renderer_;
|
||||
std::vector<zelda3::Room> rooms_;
|
||||
std::vector<zelda3::RoomEntrance> entrances_;
|
||||
zelda3::DungeonObjectRenderer object_renderer_;
|
||||
|
||||
absl::flat_hash_map<uint16_t, int> spriteset_usage_;
|
||||
absl::flat_hash_map<uint16_t, int> blockset_usage_;
|
||||
@@ -143,7 +140,6 @@ class DungeonEditor : public Editor,
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,52 +1,7 @@
|
||||
#include "editor.h"
|
||||
|
||||
#include "app/core/constants.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
absl::Status DrawEditor(EditorLayoutParams *params) {
|
||||
if (params->editor == nullptr) {
|
||||
return absl::InternalError("Editor is not initialized");
|
||||
}
|
||||
|
||||
// Draw the editors based on h_split and v_split in a recursive manner
|
||||
if (params->v_split) {
|
||||
ImGui::BeginTable("##VerticalSplitTable", 2);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (params->left)
|
||||
RETURN_IF_ERROR(DrawEditor(params->left));
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (params->right)
|
||||
RETURN_IF_ERROR(DrawEditor(params->right));
|
||||
|
||||
ImGui::EndTable();
|
||||
} else if (params->h_split) {
|
||||
ImGui::BeginTable("##HorizontalSplitTable", 1);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (params->top)
|
||||
RETURN_IF_ERROR(DrawEditor(params->top));
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (params->bottom)
|
||||
RETURN_IF_ERROR(DrawEditor(params->bottom));
|
||||
|
||||
ImGui::EndTable();
|
||||
} else {
|
||||
// No split, just draw the single editor
|
||||
ImGui::Text("%s Editor",
|
||||
kEditorNames[static_cast<int>(params->editor->type())]);
|
||||
RETURN_IF_ERROR(params->editor->Update());
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
#include "app/editor/system/resource_manager.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
|
||||
/**
|
||||
* @namespace yaze::app::editor
|
||||
* @namespace yaze::editor
|
||||
* @brief Editors are the view controllers for the application.
|
||||
*/
|
||||
namespace editor {
|
||||
@@ -74,32 +73,7 @@ class Editor {
|
||||
EditorContext context_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Dynamic Editor Layout Parameters
|
||||
*/
|
||||
typedef struct EditorLayoutParams {
|
||||
bool v_split;
|
||||
bool h_split;
|
||||
int v_split_pos;
|
||||
int h_split_pos;
|
||||
Editor *editor = nullptr;
|
||||
EditorLayoutParams *left = nullptr;
|
||||
EditorLayoutParams *right = nullptr;
|
||||
EditorLayoutParams *top = nullptr;
|
||||
EditorLayoutParams *bottom = nullptr;
|
||||
|
||||
EditorLayoutParams() {
|
||||
v_split = false;
|
||||
h_split = false;
|
||||
v_split_pos = 0;
|
||||
h_split_pos = 0;
|
||||
}
|
||||
} EditorLayoutParams;
|
||||
|
||||
absl::Status DrawEditor(EditorLayoutParams *params);
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_CORE_EDITOR_H
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "imgui/misc/cpp/imgui_stdlib.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using namespace ImGui;
|
||||
@@ -32,8 +31,8 @@ using core::FileDialogWrapper;
|
||||
|
||||
namespace {
|
||||
|
||||
bool BeginCentered(const char* name) {
|
||||
ImGuiIO const& io = GetIO();
|
||||
bool BeginCentered(const char *name) {
|
||||
ImGuiIO const &io = GetIO();
|
||||
ImVec2 pos(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f);
|
||||
SetNextWindowPos(pos, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
ImGuiWindowFlags flags =
|
||||
@@ -42,19 +41,18 @@ bool BeginCentered(const char* name) {
|
||||
return Begin(name, nullptr, flags);
|
||||
}
|
||||
|
||||
bool IsEditorActive(Editor* editor, std::vector<Editor*>& active_editors) {
|
||||
bool IsEditorActive(Editor *editor, std::vector<Editor *> &active_editors) {
|
||||
return std::find(active_editors.begin(), active_editors.end(), editor) !=
|
||||
active_editors.end();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void EditorManager::SetupScreen(std::string filename) {
|
||||
void EditorManager::Initialize(std::string filename) {
|
||||
if (!filename.empty()) {
|
||||
PRINT_IF_ERROR(rom()->LoadFromFile(filename));
|
||||
}
|
||||
overworld_editor_.InitializeZeml();
|
||||
InitializeCommands();
|
||||
overworld_editor_.Initialize();
|
||||
}
|
||||
|
||||
absl::Status EditorManager::Update() {
|
||||
@@ -66,17 +64,12 @@ absl::Status EditorManager::Update() {
|
||||
DrawInfoPopup();
|
||||
|
||||
if (rom()->is_loaded() && !rom_assets_loaded_) {
|
||||
// Load all of the graphics data from the game.
|
||||
RETURN_IF_ERROR(rom()->LoadAllGraphicsData())
|
||||
// Initialize overworld graphics, maps, and palettes
|
||||
RETURN_IF_ERROR(overworld_editor_.LoadGraphics());
|
||||
rom_assets_loaded_ = true;
|
||||
}
|
||||
|
||||
if (dynamic_layout_)
|
||||
RETURN_IF_ERROR(DrawDynamicLayout())
|
||||
else
|
||||
ManageActiveEditors();
|
||||
ManageActiveEditors();
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
@@ -244,12 +237,6 @@ void EditorManager::ManageActiveEditors() {
|
||||
}
|
||||
}
|
||||
|
||||
absl::Status EditorManager::DrawDynamicLayout() {
|
||||
// Dynamic layout for multiple editors to be open at once
|
||||
// Allows for tiling and resizing of editors using ImGui
|
||||
return DrawEditor(&root_layout_);
|
||||
}
|
||||
|
||||
void EditorManager::ManageKeyboardShortcuts() {
|
||||
bool ctrl_or_super = (GetIO().KeyCtrl || GetIO().KeySuper);
|
||||
|
||||
@@ -309,81 +296,6 @@ void EditorManager::ManageKeyboardShortcuts() {
|
||||
}
|
||||
}
|
||||
|
||||
void EditorManager::InitializeCommands() {
|
||||
if (root_layout_.editor == nullptr) {
|
||||
root_layout_.editor = &overworld_editor_;
|
||||
}
|
||||
|
||||
// New editor popup for window management commands
|
||||
static EditorLayoutParams new_layout;
|
||||
if (ImGui::BeginPopup("NewEditor")) {
|
||||
ImGui::Text("New Editor");
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("Overworld")) {
|
||||
new_layout.editor = &overworld_editor_;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (ImGui::Button("Dungeon")) {
|
||||
new_layout.editor = &dungeon_editor_;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (ImGui::Button("Graphics")) {
|
||||
new_layout.editor = &graphics_editor_;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (ImGui::Button("Music")) {
|
||||
new_layout.editor = &music_editor_;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (ImGui::Button("Palette")) {
|
||||
new_layout.editor = &palette_editor_;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (ImGui::Button("Screen")) {
|
||||
new_layout.editor = &screen_editor_;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (ImGui::Button("Sprite")) {
|
||||
new_layout.editor = &sprite_editor_;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (ImGui::Button("Code")) {
|
||||
new_layout.editor = &assembly_editor_;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (ImGui::Button("Settings")) {
|
||||
new_layout.editor = &settings_editor_;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
if (ImGui::Button("Message")) {
|
||||
new_layout.editor = &message_editor_;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
editor_context_.command_manager.RegisterPrefix("window", 'w',
|
||||
"window management", "");
|
||||
editor_context_.command_manager.RegisterSubcommand(
|
||||
"window", "vsplit", '/', "vertical split",
|
||||
"split windows vertically and place editor in new window", [this]() {
|
||||
ImGui::OpenPopup("NewEditor");
|
||||
root_layout_.v_split = true;
|
||||
});
|
||||
editor_context_.command_manager.RegisterSubcommand(
|
||||
"window", "hsplit", '-', "horizontal split",
|
||||
"split windows horizontally and place editor in new window", [this]() {
|
||||
ImGui::OpenPopup("NewEditor");
|
||||
root_layout_.h_split = true;
|
||||
});
|
||||
editor_context_.command_manager.RegisterSubcommand(
|
||||
"window", "close", 'd', "close", "close the current editor", [this]() {
|
||||
if (root_layout_.editor != nullptr) {
|
||||
root_layout_.editor = nullptr;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void EditorManager::DrawStatusPopup() {
|
||||
static absl::Status prev_status;
|
||||
if (!status_.ok()) {
|
||||
@@ -415,7 +327,7 @@ void EditorManager::DrawStatusPopup() {
|
||||
void EditorManager::DrawAboutPopup() {
|
||||
if (about_) OpenPopup("About");
|
||||
if (BeginPopupModal("About", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
Text("Yet Another Zelda3 Editor - v%s", core::kYazeVersion.data());
|
||||
Text("Yet Another Zelda3 Editor - v%s", version_.c_str());
|
||||
Text("Written by: scawful");
|
||||
Spacing();
|
||||
Text("Special Thanks: Zarby89, JaredBrian");
|
||||
@@ -434,7 +346,7 @@ void EditorManager::DrawInfoPopup() {
|
||||
if (BeginPopupModal("ROM Information", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
Text("Title: %s", rom()->title().c_str());
|
||||
Text("ROM Size: %s", core::UppercaseHexLongLong(rom()->size()).c_str());
|
||||
Text("ROM Size: %s", core::HexLongLong(rom()->size()).c_str());
|
||||
|
||||
if (Button("Close", gui::kDefaultModalSize) ||
|
||||
IsKeyPressed(ImGuiKey_Escape)) {
|
||||
@@ -457,7 +369,7 @@ void EditorManager::DrawYazeMenu() {
|
||||
show_display_settings = !show_display_settings;
|
||||
}
|
||||
PopStyleColor();
|
||||
Text("yaze v%s", core::kYazeVersion.data());
|
||||
Text("yaze v%s", version_.c_str());
|
||||
EndMenuBar();
|
||||
}
|
||||
|
||||
@@ -483,7 +395,7 @@ void EditorManager::DrawYazeMenuBar() {
|
||||
if (manager.GetRecentFiles().empty()) {
|
||||
MenuItem("No Recent Files", nullptr, false, false);
|
||||
} else {
|
||||
for (const auto& filePath : manager.GetRecentFiles()) {
|
||||
for (const auto &filePath : manager.GetRecentFiles()) {
|
||||
if (MenuItem(filePath.c_str())) {
|
||||
OpenRomOrProject(filePath);
|
||||
}
|
||||
@@ -643,7 +555,6 @@ void EditorManager::DrawYazeMenuBar() {
|
||||
}
|
||||
|
||||
if (BeginMenu("View")) {
|
||||
MenuItem("Dynamic Layout", nullptr, &dynamic_layout_);
|
||||
MenuItem("Emulator", nullptr, &show_emulator);
|
||||
Separator();
|
||||
MenuItem("Memory Editor", nullptr, &show_memory_editor);
|
||||
@@ -772,7 +683,7 @@ void EditorManager::LoadRom() {
|
||||
}
|
||||
|
||||
void EditorManager::SaveRom() {
|
||||
if (flags()->kSaveDungeonMaps) {
|
||||
if (core::ExperimentFlags::get().kSaveDungeonMaps) {
|
||||
status_ = screen_editor_.SaveDungeonMaps();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
}
|
||||
@@ -783,7 +694,7 @@ void EditorManager::SaveRom() {
|
||||
status_ = rom()->SaveToFile(backup_rom_, save_new_auto_);
|
||||
}
|
||||
|
||||
void EditorManager::OpenRomOrProject(const std::string& filename) {
|
||||
void EditorManager::OpenRomOrProject(const std::string &filename) {
|
||||
if (absl::StrContains(filename, ".yaze")) {
|
||||
status_ = current_project_.Open(filename);
|
||||
if (status_.ok()) {
|
||||
@@ -816,5 +727,4 @@ absl::Status EditorManager::OpenProject() {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
#include "app/emu/emulator.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/rom.h"
|
||||
#include "yaze_config.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
/**
|
||||
@@ -35,7 +35,7 @@ namespace editor {
|
||||
* variable points to the currently active editor in the tab view.
|
||||
*
|
||||
*/
|
||||
class EditorManager : public SharedRom, public core::ExperimentFlags {
|
||||
class EditorManager : public SharedRom {
|
||||
public:
|
||||
EditorManager() {
|
||||
current_editor_ = &overworld_editor_;
|
||||
@@ -46,9 +46,13 @@ class EditorManager : public SharedRom, public core::ExperimentFlags {
|
||||
active_editors_.push_back(&sprite_editor_);
|
||||
active_editors_.push_back(&message_editor_);
|
||||
active_editors_.push_back(&screen_editor_);
|
||||
std::stringstream ss;
|
||||
ss << YAZE_VERSION_MAJOR << "." << YAZE_VERSION_MINOR << "."
|
||||
<< YAZE_VERSION_PATCH;
|
||||
ss >> version_;
|
||||
}
|
||||
|
||||
void SetupScreen(std::string filename = "");
|
||||
void Initialize(std::string filename = "");
|
||||
absl::Status Update();
|
||||
|
||||
auto emulator() -> emu::Emulator & { return emulator_; }
|
||||
@@ -56,10 +60,7 @@ class EditorManager : public SharedRom, public core::ExperimentFlags {
|
||||
|
||||
private:
|
||||
void ManageActiveEditors();
|
||||
absl::Status DrawDynamicLayout();
|
||||
|
||||
void ManageKeyboardShortcuts();
|
||||
void InitializeCommands();
|
||||
|
||||
void DrawStatusPopup();
|
||||
void DrawAboutPopup();
|
||||
@@ -81,16 +82,12 @@ class EditorManager : public SharedRom, public core::ExperimentFlags {
|
||||
bool save_new_auto_ = true;
|
||||
bool show_status_ = false;
|
||||
bool rom_assets_loaded_ = false;
|
||||
bool dynamic_layout_ = false;
|
||||
|
||||
std::string version_ = "";
|
||||
|
||||
absl::Status status_;
|
||||
|
||||
emu::Emulator emulator_;
|
||||
|
||||
std::vector<Editor *> active_editors_;
|
||||
std::vector<EditorLayoutParams> active_layouts_;
|
||||
|
||||
EditorLayoutParams root_layout_;
|
||||
|
||||
Project current_project_;
|
||||
EditorContext editor_context_;
|
||||
@@ -100,7 +97,7 @@ class EditorManager : public SharedRom, public core::ExperimentFlags {
|
||||
DungeonEditor dungeon_editor_;
|
||||
GraphicsEditor graphics_editor_;
|
||||
MusicEditor music_editor_;
|
||||
OverworldEditor overworld_editor_;
|
||||
OverworldEditor overworld_editor_{*rom()};
|
||||
PaletteEditor palette_editor_;
|
||||
ScreenEditor screen_editor_;
|
||||
SpriteEditor sprite_editor_;
|
||||
@@ -110,7 +107,6 @@ class EditorManager : public SharedRom, public core::ExperimentFlags {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_EDITOR_MANAGER_H
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using ImGui::BeginChild;
|
||||
@@ -297,5 +296,4 @@ void GfxGroupEditor::DrawPaletteViewer() {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "app/rom.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
/**
|
||||
@@ -43,6 +42,5 @@ class GfxGroupEditor : public SharedRom {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
#endif // YAZE_APP_EDITOR_GFX_GROUP_EDITOR_H
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include "graphics_editor.h"
|
||||
|
||||
#include "ImGuiFileDialog/ImGuiFileDialog.h"
|
||||
#include <filesystem>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "app/core/platform/clipboard.h"
|
||||
#include "app/core/platform/file_dialog.h"
|
||||
#include "app/core/platform/renderer.h"
|
||||
#include "app/editor/graphics/palette_editor.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
@@ -23,7 +25,6 @@
|
||||
#include "imgui_memory_editor.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using core::Renderer;
|
||||
@@ -515,22 +516,19 @@ absl::Status GraphicsEditor::DrawCgxImport() {
|
||||
gui::TextWithSeparators("Cgx Import");
|
||||
InputInt("BPP", ¤t_bpp_);
|
||||
|
||||
InputText("##CGXFile", cgx_file_name_, sizeof(cgx_file_name_));
|
||||
InputText("##CGXFile", &cgx_file_name_);
|
||||
SameLine();
|
||||
|
||||
gui::FileDialogPipeline("ImportCgxKey", ".CGX,.cgx\0", "Open CGX", [this]() {
|
||||
strncpy(cgx_file_path_,
|
||||
ImGuiFileDialog::Instance()->GetFilePathName().c_str(),
|
||||
sizeof(cgx_file_path_));
|
||||
strncpy(cgx_file_name_,
|
||||
ImGuiFileDialog::Instance()->GetCurrentFileName().c_str(),
|
||||
sizeof(cgx_file_name_));
|
||||
if (ImGui::Button("Open CGX")) {
|
||||
auto filename = core::FileDialogWrapper::ShowOpenFileDialog();
|
||||
cgx_file_name_ = filename;
|
||||
cgx_file_path_ = std::filesystem::absolute(filename).string();
|
||||
is_open_ = true;
|
||||
cgx_loaded_ = true;
|
||||
});
|
||||
}
|
||||
|
||||
if (ImGui::Button("Copy CGX Path")) {
|
||||
ImGui::SetClipboardText(cgx_file_path_);
|
||||
ImGui::SetClipboardText(cgx_file_path_.c_str());
|
||||
}
|
||||
|
||||
if (ImGui::Button("Load CGX Data")) {
|
||||
@@ -548,19 +546,15 @@ absl::Status GraphicsEditor::DrawCgxImport() {
|
||||
}
|
||||
|
||||
absl::Status GraphicsEditor::DrawScrImport() {
|
||||
InputText("##ScrFile", scr_file_name_, sizeof(scr_file_name_));
|
||||
InputText("##ScrFile", &scr_file_name_);
|
||||
|
||||
gui::FileDialogPipeline(
|
||||
"ImportScrKey", ".SCR,.scr,.BAK\0", "Open SCR", [this]() {
|
||||
strncpy(scr_file_path_,
|
||||
ImGuiFileDialog::Instance()->GetFilePathName().c_str(),
|
||||
sizeof(scr_file_path_));
|
||||
strncpy(scr_file_name_,
|
||||
ImGuiFileDialog::Instance()->GetCurrentFileName().c_str(),
|
||||
sizeof(scr_file_name_));
|
||||
is_open_ = true;
|
||||
scr_loaded_ = true;
|
||||
});
|
||||
if (ImGui::Button("Open SCR")) {
|
||||
auto filename = core::FileDialogWrapper::ShowOpenFileDialog();
|
||||
scr_file_name_ = filename;
|
||||
scr_file_path_ = std::filesystem::absolute(filename).string();
|
||||
is_open_ = true;
|
||||
scr_loaded_ = true;
|
||||
}
|
||||
|
||||
InputInt("SCR Mod", &scr_mod_value_);
|
||||
|
||||
@@ -584,38 +578,35 @@ absl::Status GraphicsEditor::DrawScrImport() {
|
||||
|
||||
absl::Status GraphicsEditor::DrawPaletteControls() {
|
||||
gui::TextWithSeparators("COL Import");
|
||||
InputText("##ColFile", col_file_name_, sizeof(col_file_name_));
|
||||
InputText("##ColFile", &col_file_name_);
|
||||
SameLine();
|
||||
|
||||
gui::FileDialogPipeline(
|
||||
"ImportColKey", ".COL,.col,.BAK,.bak\0", "Open COL", [this]() {
|
||||
strncpy(col_file_path_,
|
||||
ImGuiFileDialog::Instance()->GetFilePathName().c_str(),
|
||||
sizeof(col_file_path_));
|
||||
strncpy(col_file_name_,
|
||||
ImGuiFileDialog::Instance()->GetCurrentFileName().c_str(),
|
||||
sizeof(col_file_name_));
|
||||
status_ = temp_rom_.LoadFromFile(col_file_path_,
|
||||
/*z3_load=*/false);
|
||||
auto col_data_ = gfx::GetColFileData(temp_rom_.data());
|
||||
if (col_file_palette_group_.size() != 0) {
|
||||
col_file_palette_group_.clear();
|
||||
}
|
||||
auto col_file_palette_group_status =
|
||||
gfx::CreatePaletteGroupFromColFile(col_data_);
|
||||
if (col_file_palette_group_status.ok()) {
|
||||
col_file_palette_group_ = col_file_palette_group_status.value();
|
||||
}
|
||||
col_file_palette_ = gfx::SnesPalette(col_data_);
|
||||
if (ImGui::Button("Open COL")) {
|
||||
auto filename = core::FileDialogWrapper::ShowOpenFileDialog();
|
||||
col_file_name_ = filename;
|
||||
col_file_path_ = std::filesystem::absolute(filename).string();
|
||||
status_ = temp_rom_.LoadFromFile(col_file_path_,
|
||||
/*z3_load=*/false);
|
||||
auto col_data_ = gfx::GetColFileData(temp_rom_.mutable_data());
|
||||
if (col_file_palette_group_.size() != 0) {
|
||||
col_file_palette_group_.clear();
|
||||
}
|
||||
auto col_file_palette_group_status =
|
||||
gfx::CreatePaletteGroupFromColFile(col_data_);
|
||||
if (col_file_palette_group_status.ok()) {
|
||||
col_file_palette_group_ = col_file_palette_group_status.value();
|
||||
}
|
||||
col_file_palette_ = gfx::SnesPalette(col_data_);
|
||||
|
||||
// gigaleak dev format based code
|
||||
decoded_col_ = gfx::scad_format::DecodeColFile(col_file_path_);
|
||||
col_file_ = true;
|
||||
is_open_ = true;
|
||||
});
|
||||
// gigaleak dev format based code
|
||||
decoded_col_ = gfx::scad_format::DecodeColFile(col_file_path_);
|
||||
col_file_ = true;
|
||||
is_open_ = true;
|
||||
}
|
||||
HOVER_HINT(".COL, .BAK");
|
||||
|
||||
if (ImGui::Button("Copy Col Path")) {
|
||||
ImGui::SetClipboardText(col_file_path_);
|
||||
ImGui::SetClipboardText(col_file_path_.c_str());
|
||||
}
|
||||
|
||||
if (rom()->is_loaded()) {
|
||||
@@ -636,17 +627,17 @@ absl::Status GraphicsEditor::DrawPaletteControls() {
|
||||
absl::Status GraphicsEditor::DrawObjImport() {
|
||||
gui::TextWithSeparators("OBJ Import");
|
||||
|
||||
InputText("##ObjFile", obj_file_path_, sizeof(obj_file_path_));
|
||||
InputText("##ObjFile", &obj_file_path_);
|
||||
SameLine();
|
||||
|
||||
gui::FileDialogPipeline(
|
||||
"ImportObjKey", ".obj,.OBJ,.bak,.BAK\0", "Open OBJ", [this]() {
|
||||
strncpy(file_path_,
|
||||
ImGuiFileDialog::Instance()->GetFilePathName().c_str(),
|
||||
sizeof(file_path_));
|
||||
status_ = temp_rom_.LoadFromFile(file_path_);
|
||||
is_open_ = true;
|
||||
});
|
||||
if (ImGui::Button("Open OBJ")) {
|
||||
auto filename = core::FileDialogWrapper::ShowOpenFileDialog();
|
||||
obj_file_path_ = std::filesystem::absolute(filename).string();
|
||||
status_ = temp_rom_.LoadFromFile(obj_file_path_);
|
||||
is_open_ = true;
|
||||
obj_loaded_ = true;
|
||||
}
|
||||
HOVER_HINT(".OBJ, .BAK");
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
@@ -654,23 +645,22 @@ absl::Status GraphicsEditor::DrawObjImport() {
|
||||
absl::Status GraphicsEditor::DrawTilemapImport() {
|
||||
gui::TextWithSeparators("Tilemap Import");
|
||||
|
||||
InputText("##TMapFile", tilemap_file_path_, sizeof(tilemap_file_path_));
|
||||
InputText("##TMapFile", &tilemap_file_path_);
|
||||
SameLine();
|
||||
|
||||
gui::FileDialogPipeline(
|
||||
"ImportTilemapKey", ".DAT,.dat,.BIN,.bin,.hex,.HEX\0", "Open Tilemap",
|
||||
[this]() {
|
||||
strncpy(tilemap_file_path_,
|
||||
ImGuiFileDialog::Instance()->GetFilePathName().c_str(),
|
||||
sizeof(tilemap_file_path_));
|
||||
status_ = tilemap_rom_.LoadFromFile(tilemap_file_path_);
|
||||
if (ImGui::Button("Open Tilemap")) {
|
||||
auto filename = core::FileDialogWrapper::ShowOpenFileDialog();
|
||||
tilemap_file_path_ = std::filesystem::absolute(filename).string();
|
||||
status_ = tilemap_rom_.LoadFromFile(tilemap_file_path_);
|
||||
status_ = tilemap_rom_.LoadFromFile(tilemap_file_path_);
|
||||
|
||||
// Extract the high and low bytes from the file.
|
||||
auto decomp_sheet = gfx::lc_lz2::DecompressV2(
|
||||
tilemap_rom_.data(), gfx::lc_lz2::kNintendoMode1);
|
||||
tilemap_loaded_ = true;
|
||||
is_open_ = true;
|
||||
});
|
||||
// Extract the high and low bytes from the file.
|
||||
auto decomp_sheet = gfx::lc_lz2::DecompressV2(tilemap_rom_.data(),
|
||||
gfx::lc_lz2::kNintendoMode1);
|
||||
tilemap_loaded_ = true;
|
||||
is_open_ = true;
|
||||
}
|
||||
HOVER_HINT(".DAT, .BIN, .HEX");
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
@@ -678,30 +668,30 @@ absl::Status GraphicsEditor::DrawTilemapImport() {
|
||||
absl::Status GraphicsEditor::DrawFileImport() {
|
||||
gui::TextWithSeparators("BIN Import");
|
||||
|
||||
InputText("##ROMFile", file_path_, sizeof(file_path_));
|
||||
InputText("##ROMFile", &file_path_);
|
||||
SameLine();
|
||||
|
||||
gui::FileDialogPipeline("ImportDlgKey", ".bin,.hex\0", "Open BIN", [this]() {
|
||||
strncpy(file_path_, ImGuiFileDialog::Instance()->GetFilePathName().c_str(),
|
||||
sizeof(file_path_));
|
||||
if (ImGui::Button("Open BIN")) {
|
||||
auto filename = core::FileDialogWrapper::ShowOpenFileDialog();
|
||||
file_path_ = filename;
|
||||
status_ = temp_rom_.LoadFromFile(file_path_);
|
||||
is_open_ = true;
|
||||
});
|
||||
}
|
||||
HOVER_HINT(".BIN, .HEX");
|
||||
|
||||
if (Button("Copy File Path")) {
|
||||
ImGui::SetClipboardText(file_path_);
|
||||
ImGui::SetClipboardText(file_path_.c_str());
|
||||
}
|
||||
|
||||
gui::InputHex("BIN Offset", ¤t_offset_);
|
||||
gui::InputHex("BIN Size", &bin_size_);
|
||||
|
||||
if (Button("Decompress BIN")) {
|
||||
if (strlen(file_path_) > 0) {
|
||||
RETURN_IF_ERROR(DecompressImportData(bin_size_))
|
||||
} else {
|
||||
if (file_path_.empty()) {
|
||||
return absl::InvalidArgumentError(
|
||||
"Please select a file before importing.");
|
||||
"Please select a file before decompressing.");
|
||||
}
|
||||
RETURN_IF_ERROR(DecompressImportData(bin_size_))
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
@@ -740,13 +730,12 @@ absl::Status GraphicsEditor::DrawClipboardImport() {
|
||||
absl::Status GraphicsEditor::DrawExperimentalFeatures() {
|
||||
gui::TextWithSeparators("Experimental");
|
||||
if (Button("Decompress Super Donkey Full")) {
|
||||
if (strlen(file_path_) > 0) {
|
||||
RETURN_IF_ERROR(DecompressSuperDonkey())
|
||||
} else {
|
||||
if (file_path_.empty()) {
|
||||
return absl::InvalidArgumentError(
|
||||
"Please select `super_donkey_1.bin` before "
|
||||
"importing.");
|
||||
}
|
||||
RETURN_IF_ERROR(DecompressSuperDonkey())
|
||||
}
|
||||
ImGui::SetItemTooltip(
|
||||
"Requires `super_donkey_1.bin` to be imported under the "
|
||||
@@ -758,7 +747,8 @@ absl::Status GraphicsEditor::DrawMemoryEditor() {
|
||||
std::string title = "Memory Editor";
|
||||
if (is_open_) {
|
||||
static MemoryEditor mem_edit;
|
||||
mem_edit.DrawWindow(title.c_str(), temp_rom_.data(), temp_rom_.size());
|
||||
mem_edit.DrawWindow(title.c_str(), temp_rom_.mutable_data(),
|
||||
temp_rom_.size());
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
@@ -844,5 +834,4 @@ absl::Status GraphicsEditor::DecompressSuperDonkey() {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -4,19 +4,18 @@
|
||||
#include <stack>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "app/editor/graphics/palette_editor.h"
|
||||
#include "app/editor/editor.h"
|
||||
#include "app/editor/graphics/palette_editor.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/gui/modules/asset_browser.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/modules/asset_browser.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/overworld/overworld.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui_memory_editor.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
// "99973","A3D80",
|
||||
@@ -143,16 +142,16 @@ class GraphicsEditor : public SharedRom, public Editor {
|
||||
bool obj_loaded_ = false;
|
||||
bool tilemap_loaded_ = false;
|
||||
|
||||
char file_path_[256] = "";
|
||||
char col_file_path_[256] = "";
|
||||
char col_file_name_[256] = "";
|
||||
char cgx_file_path_[256] = "";
|
||||
char cgx_file_name_[256] = "";
|
||||
char scr_file_path_[256] = "";
|
||||
char scr_file_name_[256] = "";
|
||||
char obj_file_path_[256] = "";
|
||||
char tilemap_file_path_[256] = "";
|
||||
char tilemap_file_name_[256] = "";
|
||||
std::string file_path_ = "";
|
||||
std::string col_file_path_ = "";
|
||||
std::string col_file_name_ = "";
|
||||
std::string cgx_file_path_ = "";
|
||||
std::string cgx_file_name_ = "";
|
||||
std::string scr_file_path_ = "";
|
||||
std::string scr_file_name_ = "";
|
||||
std::string obj_file_path_ = "";
|
||||
std::string tilemap_file_path_ = "";
|
||||
std::string tilemap_file_name_ = "";
|
||||
|
||||
gui::GfxSheetAssetBrowser asset_browser_;
|
||||
|
||||
@@ -160,7 +159,7 @@ class GraphicsEditor : public SharedRom, public Editor {
|
||||
|
||||
Rom temp_rom_;
|
||||
Rom tilemap_rom_;
|
||||
zelda3::overworld::Overworld overworld_;
|
||||
zelda3::Overworld overworld_;
|
||||
MemoryEditor cgx_memory_editor_;
|
||||
MemoryEditor col_memory_editor_;
|
||||
PaletteEditor palette_editor_;
|
||||
@@ -196,7 +195,6 @@ class GraphicsEditor : public SharedRom, public Editor {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_GRAPHICS_EDITOR_H
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using ImGui::AcceptDragDropPayload;
|
||||
@@ -472,5 +471,4 @@ absl::Status PaletteEditor::ResetColorToOriginal(
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
namespace palette_internal {
|
||||
@@ -120,7 +119,6 @@ class PaletteEditor : public SharedRom, public Editor {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/gfx/tilesheet.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/color.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using core::Renderer;
|
||||
@@ -167,7 +167,7 @@ absl::Status ScreenEditor::LoadDungeonMaps() {
|
||||
gdata[j] = rom()->data()[pc_ptr_gfx++];
|
||||
}
|
||||
|
||||
std::string label = core::UppercaseHexByte(rdata[j]);
|
||||
std::string label = core::HexByte(rdata[j]);
|
||||
dungeon_map_labels_[d][i][j] = label;
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@ void ScreenEditor::DrawDungeonMapsTabs() {
|
||||
std::string label =
|
||||
dungeon_map_labels_[selected_dungeon][floor_number][j];
|
||||
screen_canvas_.DrawText(label, (posX * 2), (posY * 2));
|
||||
std::string gfx_id = core::UppercaseHexByte(tile16_id);
|
||||
std::string gfx_id = core::HexByte(tile16_id);
|
||||
screen_canvas_.DrawText(gfx_id, (posX * 2), (posY * 2) + 16);
|
||||
}
|
||||
}
|
||||
@@ -392,13 +392,30 @@ void ScreenEditor::DrawDungeonMapsEditor() {
|
||||
sheets_.emplace(1, rom()->gfx_sheets()[213]);
|
||||
sheets_.emplace(2, rom()->gfx_sheets()[214]);
|
||||
sheets_.emplace(3, rom()->gfx_sheets()[215]);
|
||||
int current_tile8 = 0;
|
||||
int tile_data_offset = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (int j = 0; j < 32; j++) {
|
||||
std::vector<uint8_t> tile_data(64, 0); // 8x8 tile (64 bytes
|
||||
int tile_index = current_tile8 + j;
|
||||
int x = (j % 8) * 8;
|
||||
int y = (j / 8) * 8;
|
||||
sheets_[i].Get8x8Tile(tile_index, 0, 0, tile_data, tile_data_offset);
|
||||
tile8_individual_.emplace_back(gfx::Bitmap(8, 8, 4, tile_data));
|
||||
RETURN_VOID_IF_ERROR(tile8_individual_.back().ApplyPalette(
|
||||
*rom()->mutable_dungeon_palette(3)));
|
||||
Renderer::GetInstance().RenderBitmap(&tile8_individual_.back());
|
||||
}
|
||||
tile_data_offset = 0;
|
||||
}
|
||||
dungeon_maps_loaded_ = true;
|
||||
} else {
|
||||
ImGui::Text("Failed to load dungeon map tile16");
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("##DungeonMapToolset", 2, ImGuiTableFlags_SizingFixedFit)) {
|
||||
if (ImGui::BeginTable("##DungeonMapToolset", 2,
|
||||
ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableSetupColumn("Draw Mode");
|
||||
ImGui::TableSetupColumn("Edit Mode");
|
||||
|
||||
@@ -470,8 +487,13 @@ void ScreenEditor::DrawDungeonMapsEditor() {
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
current_tile_canvas_.DrawBackground(ImVec2(64 * 2 + 2, 64 * 2 + 4));
|
||||
current_tile_canvas_
|
||||
.DrawBackground(); // ImVec2(64 * 2 + 2, 64 * 2 + 4));
|
||||
current_tile_canvas_.DrawContextMenu();
|
||||
if (current_tile_canvas_.DrawTilePainter(
|
||||
tile8_individual_[selected_tile8_], 16)) {
|
||||
// Modify the tile16 based on the selected tile and current_tile16_info
|
||||
}
|
||||
current_tile_canvas_.DrawBitmap(tile16_individual_[selected_tile16_], 2,
|
||||
4.0f);
|
||||
current_tile_canvas_.DrawGrid(16.f);
|
||||
@@ -538,8 +560,10 @@ void ScreenEditor::LoadBinaryGfx() {
|
||||
gfx_sheets.emplace_back(converted_bin.begin() + (i * 0x1000),
|
||||
converted_bin.begin() + ((i + 1) * 0x1000));
|
||||
sheets_.emplace(i, gfx::Bitmap(128, 32, 8, gfx_sheets[i]));
|
||||
sheets_[i].ApplyPalette(*rom()->mutable_dungeon_palette(3));
|
||||
Renderer::GetInstance().RenderBitmap(&sheets_[i]);
|
||||
status_ = sheets_[i].ApplyPalette(*rom()->mutable_dungeon_palette(3));
|
||||
if (status_.ok()) {
|
||||
Renderer::GetInstance().RenderBitmap(&sheets_[i]);
|
||||
}
|
||||
}
|
||||
binary_gfx_loaded_ = true;
|
||||
} else {
|
||||
@@ -589,5 +613,4 @@ void ScreenEditor::DrawToolset() {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
/**
|
||||
@@ -33,7 +32,7 @@ namespace editor {
|
||||
* The class inherits from the SharedRom class.
|
||||
*/
|
||||
class ScreenEditor : public SharedRom, public Editor {
|
||||
public:
|
||||
public:
|
||||
ScreenEditor() {
|
||||
screen_canvas_.SetCanvasSize(ImVec2(512, 512));
|
||||
type_ = EditorType::kScreen;
|
||||
@@ -50,7 +49,7 @@ public:
|
||||
|
||||
absl::Status SaveDungeonMaps();
|
||||
|
||||
private:
|
||||
private:
|
||||
void DrawTitleScreenEditor();
|
||||
void DrawNamingScreenEditor();
|
||||
void DrawOverworldMapEditor();
|
||||
@@ -86,12 +85,13 @@ private:
|
||||
bool copy_button_pressed = false;
|
||||
bool paste_button_pressed = false;
|
||||
|
||||
std::vector<uint8_t> all_gfx_;
|
||||
std::array<uint16_t, 4> current_tile16_data_;
|
||||
std::unordered_map<int, gfx::Bitmap> tile16_individual_;
|
||||
std::vector<gfx::Bitmap> tile8_individual_;
|
||||
std::vector<uint8_t> all_gfx_;
|
||||
std::vector<uint8_t> gfx_bin_data_;
|
||||
std::vector<zelda3::screen::DungeonMap> dungeon_maps_;
|
||||
std::vector<std::vector<std::array<std::string, 25>>> dungeon_map_labels_;
|
||||
std::array<uint16_t, 4> current_tile16_data_;
|
||||
std::vector<uint8_t> gfx_bin_data_;
|
||||
|
||||
absl::Status status_;
|
||||
|
||||
@@ -100,18 +100,17 @@ private:
|
||||
gfx::Tilesheet tile16_sheet_;
|
||||
gfx::InternalTile16 current_tile16_info;
|
||||
|
||||
gui::Canvas current_tile_canvas_{"##CurrentTileCanvas"};
|
||||
gui::Canvas current_tile_canvas_{"##CurrentTileCanvas", ImVec2(32, 32),
|
||||
gui::CanvasGridSize::k16x16, 2.0f};
|
||||
gui::Canvas screen_canvas_;
|
||||
gui::Canvas tilesheet_canvas_;
|
||||
gui::Canvas tilemap_canvas_{"##TilemapCanvas",
|
||||
ImVec2(128 + 2, (192) + 4),
|
||||
gui::Canvas tilemap_canvas_{"##TilemapCanvas", ImVec2(128 + 2, (192) + 4),
|
||||
gui::CanvasGridSize::k8x8, 2.f};
|
||||
|
||||
zelda3::screen::Inventory inventory_;
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace editor
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "ImGuiFileDialog/ImGuiFileDialog.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "app/core/platform/file_dialog.h"
|
||||
#include "app/core/platform/renderer.h"
|
||||
#include "app/editor/graphics/palette_editor.h"
|
||||
#include "app/editor/editor.h"
|
||||
#include "app/editor/graphics/palette_editor.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using core::Renderer;
|
||||
@@ -52,7 +51,7 @@ using ImGui::Text;
|
||||
absl::Status Tile16Editor::InitBlockset(
|
||||
const gfx::Bitmap& tile16_blockset_bmp, const gfx::Bitmap& current_gfx_bmp,
|
||||
const std::vector<gfx::Bitmap>& tile16_individual,
|
||||
uint8_t all_tiles_types[0x200]) {
|
||||
std::array<uint8_t, 0x200>& all_tiles_types) {
|
||||
all_tiles_types_ = all_tiles_types;
|
||||
tile16_blockset_bmp_ = tile16_blockset_bmp;
|
||||
tile16_individual_ = tile16_individual;
|
||||
@@ -60,7 +59,7 @@ absl::Status Tile16Editor::InitBlockset(
|
||||
RETURN_IF_ERROR(LoadTile8());
|
||||
ImVector<std::string> tile16_names;
|
||||
for (int i = 0; i < 0x200; ++i) {
|
||||
std::string str = core::UppercaseHexByte(all_tiles_types_[i]);
|
||||
std::string str = core::HexByte(all_tiles_types_[i]);
|
||||
tile16_names.push_back(str);
|
||||
}
|
||||
|
||||
@@ -251,7 +250,7 @@ absl::Status Tile16Editor::DrawTileEditControls() {
|
||||
gui::InputHexByte("Palette", ¬ify_palette.mutable_get());
|
||||
notify_palette.apply_changes();
|
||||
if (notify_palette.modified()) {
|
||||
auto palette = palettesets_[current_palette_].main;
|
||||
auto palette = palettesets_[current_palette_].main_;
|
||||
auto value = notify_palette.get();
|
||||
if (notify_palette.get() > 0x04 && notify_palette.get() < 0x06) {
|
||||
palette = palettesets_[current_palette_].aux1;
|
||||
@@ -364,16 +363,10 @@ absl::Status Tile16Editor::UpdateTile16Transfer() {
|
||||
absl::Status Tile16Editor::UpdateTransferTileCanvas() {
|
||||
// Create a button for loading another ROM
|
||||
if (Button("Load ROM")) {
|
||||
ImGuiFileDialog::Instance()->OpenDialog(
|
||||
"ChooseTransferFileDlgKey", "Open Transfer ROM", ".sfc,.smc", ".");
|
||||
auto file_name = core::FileDialogWrapper::ShowOpenFileDialog();
|
||||
transfer_status_ = transfer_rom_.LoadFromFile(file_name);
|
||||
transfer_started_ = true;
|
||||
}
|
||||
gui::FileDialogPipeline(
|
||||
"ChooseTransferFileDlgKey", ".sfc,.smc", std::nullopt, [&]() {
|
||||
std::string filePathName =
|
||||
ImGuiFileDialog::Instance()->GetFilePathName();
|
||||
transfer_status_ = transfer_rom_.LoadFromFile(filePathName);
|
||||
transfer_started_ = true;
|
||||
});
|
||||
|
||||
// TODO: Implement tile16 transfer
|
||||
if (transfer_started_ && !transfer_blockset_loaded_) {
|
||||
@@ -400,5 +393,4 @@ absl::Status Tile16Editor::UpdateTransferTileCanvas() {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -13,18 +13,17 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
/**
|
||||
* @brief Popup window to edit Tile16 data
|
||||
*/
|
||||
class Tile16Editor : public GfxContext, public SharedRom {
|
||||
class Tile16Editor : public gfx::GfxContext, public SharedRom {
|
||||
public:
|
||||
absl::Status InitBlockset(const gfx::Bitmap& tile16_blockset_bmp,
|
||||
const gfx::Bitmap& current_gfx_bmp,
|
||||
const std::vector<gfx::Bitmap>& tile16_individual,
|
||||
uint8_t all_tiles_types[0x200]);
|
||||
std::array<uint8_t, 0x200>& all_tiles_types);
|
||||
|
||||
absl::Status Update();
|
||||
absl::Status DrawMenu();
|
||||
@@ -63,7 +62,7 @@ class Tile16Editor : public GfxContext, public SharedRom {
|
||||
bool priority_tile;
|
||||
int tile_size;
|
||||
|
||||
uint8_t* all_tiles_types_;
|
||||
std::array<uint8_t, 0x200> all_tiles_types_;
|
||||
|
||||
// Tile16 blockset for selecting the tile to edit
|
||||
gui::Canvas blockset_canvas_{"blocksetCanvas", ImVec2(0x100, 0x4000),
|
||||
@@ -91,7 +90,7 @@ class Tile16Editor : public GfxContext, public SharedRom {
|
||||
PaletteEditor palette_editor_;
|
||||
|
||||
gfx::SnesPalette palette_;
|
||||
zelda3::overworld::Overworld transfer_overworld_;
|
||||
zelda3::Overworld transfer_overworld_;
|
||||
|
||||
absl::Status status_;
|
||||
|
||||
@@ -100,6 +99,5 @@ class Tile16Editor : public GfxContext, public SharedRom {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
#endif // YAZE_APP_EDITOR_TILE16EDITOR_H
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "app/core/common.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
uint8_t FindMatchingCharacter(char value) {
|
||||
@@ -145,7 +144,7 @@ std::vector<uint8_t> ParseMessageToData(std::string str) {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
std::vector<DictionaryEntry> BuildDictionaryEntries(app::Rom* rom) {
|
||||
std::vector<DictionaryEntry> BuildDictionaryEntries(Rom* rom) {
|
||||
std::vector<DictionaryEntry> AllDictionaries;
|
||||
for (int i = 0; i < kNumDictionaryEntries; i++) {
|
||||
std::vector<uint8_t> bytes;
|
||||
@@ -178,5 +177,4 @@ std::vector<DictionaryEntry> BuildDictionaryEntries(app::Rom* rom) {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "app/rom.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
const uint8_t kMessageTerminator = 0x7F;
|
||||
@@ -78,7 +77,7 @@ constexpr int kTextDataEnd = 0xE7FFF;
|
||||
constexpr int kNumDictionaryEntries = 97;
|
||||
constexpr int kPointersDictionaries = 0x74703;
|
||||
|
||||
std::vector<DictionaryEntry> BuildDictionaryEntries(app::Rom* rom);
|
||||
std::vector<DictionaryEntry> BuildDictionaryEntries(Rom* rom);
|
||||
|
||||
std::string ReplaceAllDictionaryWords(std::string str,
|
||||
std::vector<DictionaryEntry> dictionary);
|
||||
@@ -278,7 +277,6 @@ ParsedElement FindMatchingElement(const std::string& str);
|
||||
std::string ParseTextDataByte(uint8_t value);
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_MESSAGE_MESSAGE_DATA_H
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
#include "app/gui/style.h"
|
||||
#include "app/rom.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui/misc/cpp/imgui_stdlib.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using core::Renderer;
|
||||
@@ -88,7 +88,7 @@ absl::Status MessageEditor::Initialize() {
|
||||
|
||||
for (const auto& each_message : list_of_texts_) {
|
||||
std::cout << "Message #" << each_message.ID << " at address "
|
||||
<< core::UppercaseHexLong(each_message.Address) << std::endl;
|
||||
<< core::HexLong(each_message.Address) << std::endl;
|
||||
std::cout << " " << each_message.RawString << std::endl;
|
||||
|
||||
// Each string has a [:XX] char encoded
|
||||
@@ -162,10 +162,6 @@ absl::Status MessageEditor::Update() {
|
||||
}
|
||||
|
||||
void MessageEditor::DrawMessageList() {
|
||||
if (InputText("Search", &search_text_)) {
|
||||
// TODO: ImGui style text filtering
|
||||
}
|
||||
|
||||
if (BeginChild("##MessagesList", ImVec2(0, 0), true,
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
|
||||
if (BeginTable("##MessagesTable", 3, kMessageTableFlags)) {
|
||||
@@ -177,7 +173,7 @@ void MessageEditor::DrawMessageList() {
|
||||
|
||||
for (const auto& message : list_of_texts_) {
|
||||
TableNextColumn();
|
||||
if (Button(core::UppercaseHexWord(message.ID).c_str())) {
|
||||
if (Button(core::HexWord(message.ID).c_str())) {
|
||||
current_message_ = message;
|
||||
DrawMessagePreview();
|
||||
}
|
||||
@@ -186,7 +182,7 @@ void MessageEditor::DrawMessageList() {
|
||||
TableNextColumn();
|
||||
TextWrapped(
|
||||
"%s",
|
||||
core::UppercaseHexLong(list_of_texts_[message.ID].Address).c_str());
|
||||
core::HexLong(list_of_texts_[message.ID].Address).c_str());
|
||||
}
|
||||
|
||||
EndTable();
|
||||
@@ -256,7 +252,7 @@ void MessageEditor::DrawDictionary() {
|
||||
|
||||
for (const auto& dictionary : all_dictionaries_) {
|
||||
TableNextColumn();
|
||||
Text("%s", core::UppercaseHexWord(dictionary.ID).c_str());
|
||||
Text("%s", core::HexWord(dictionary.ID).c_str());
|
||||
TableNextColumn();
|
||||
Text("%s", dictionary.Contents.c_str());
|
||||
}
|
||||
@@ -336,13 +332,14 @@ void MessageEditor::ReadAllTextDataV2() {
|
||||
current_raw_message.append("[");
|
||||
current_raw_message.append(DICTIONARYTOKEN);
|
||||
current_raw_message.append(":");
|
||||
current_raw_message.append(core::UppercaseHexWord(dictionary));
|
||||
current_raw_message.append(core::HexWord(dictionary));
|
||||
current_raw_message.append("]");
|
||||
|
||||
uint32_t address = core::Get24LocalFromPC(
|
||||
rom()->data(), kPointersDictionaries + (dictionary * 2));
|
||||
rom()->mutable_data(), kPointersDictionaries + (dictionary * 2));
|
||||
uint32_t address_end = core::Get24LocalFromPC(
|
||||
rom()->data(), kPointersDictionaries + ((dictionary + 1) * 2));
|
||||
rom()->mutable_data(),
|
||||
kPointersDictionaries + ((dictionary + 1) * 2));
|
||||
|
||||
for (uint32_t i = address; i < address_end; i++) {
|
||||
parsed_message.push_back(rom()->data()[i]);
|
||||
@@ -435,13 +432,13 @@ void MessageEditor::ReadAllTextData() {
|
||||
current_message_raw.append("[");
|
||||
current_message_raw.append(DICTIONARYTOKEN);
|
||||
current_message_raw.append(":");
|
||||
current_message_raw.append(core::UppercaseHexWord(dictionary));
|
||||
current_message_raw.append(core::HexWord(dictionary));
|
||||
current_message_raw.append("]");
|
||||
|
||||
uint32_t address = core::Get24LocalFromPC(
|
||||
rom()->data(), kPointersDictionaries + (dictionary * 2));
|
||||
rom()->mutable_data(), kPointersDictionaries + (dictionary * 2));
|
||||
uint32_t address_end = core::Get24LocalFromPC(
|
||||
rom()->data(), kPointersDictionaries + ((dictionary + 1) * 2));
|
||||
rom()->mutable_data(), kPointersDictionaries + ((dictionary + 1) * 2));
|
||||
|
||||
for (uint32_t i = address; i < address_end; i++) {
|
||||
temp_bytes_parsed.push_back(rom()->data()[i]);
|
||||
@@ -703,5 +700,4 @@ void MessageEditor::SelectAll() {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "app/rom.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
constexpr int kGfxFont = 0x70000; // 2bpp format
|
||||
@@ -163,7 +162,6 @@ class MessageEditor : public Editor, public SharedRom {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_MESSAGE_EDITOR_H
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "app/gui/input.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
absl::Status MusicEditor::Update() {
|
||||
@@ -218,5 +217,4 @@ void MusicEditor::DrawToolset() {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
static const char* kGameSongs[] = {"Title",
|
||||
@@ -85,7 +84,6 @@ class MusicEditor : public SharedRom, public Editor {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "app/gui/style.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using ImGui::BeginChild;
|
||||
@@ -92,7 +91,7 @@ void HandleEntityDragging(zelda3::GameEntity *entity, ImVec2 canvas_p0,
|
||||
ImGui::SetDragDropPayload("ENTITY_PAYLOAD", &entity,
|
||||
sizeof(zelda3::GameEntity));
|
||||
Text("Moving %s ID: %s", entity_type.c_str(),
|
||||
core::UppercaseHexByte(entity->entity_id_).c_str());
|
||||
core::HexByte(entity->entity_id_).c_str());
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
MoveEntityOnGrid(dragged_entity, canvas_p0, scrolling, free_movement);
|
||||
@@ -128,7 +127,7 @@ bool DrawEntranceInserterPopup() {
|
||||
|
||||
// TODO: Implement deleting OverworldEntrance objects, currently only hides them
|
||||
bool DrawOverworldEntrancePopup(
|
||||
zelda3::overworld::OverworldEntrance &entrance) {
|
||||
zelda3::OverworldEntrance &entrance) {
|
||||
static bool set_done = false;
|
||||
if (set_done) {
|
||||
set_done = false;
|
||||
@@ -178,7 +177,7 @@ void DrawExitInserterPopup() {
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawExitEditorPopup(zelda3::overworld::OverworldExit &exit) {
|
||||
bool DrawExitEditorPopup(zelda3::OverworldExit &exit) {
|
||||
static bool set_done = false;
|
||||
if (set_done) {
|
||||
set_done = false;
|
||||
@@ -317,8 +316,8 @@ void DrawItemInsertPopup() {
|
||||
Text("Add Item");
|
||||
BeginChild("ScrollRegion", ImVec2(150, 150), true,
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
for (size_t i = 0; i < zelda3::overworld::kSecretItemNames.size(); i++) {
|
||||
if (Selectable(zelda3::overworld::kSecretItemNames[i].c_str(),
|
||||
for (size_t i = 0; i < zelda3::kSecretItemNames.size(); i++) {
|
||||
if (Selectable(zelda3::kSecretItemNames[i].c_str(),
|
||||
i == new_item_id)) {
|
||||
new_item_id = i;
|
||||
}
|
||||
@@ -341,7 +340,7 @@ void DrawItemInsertPopup() {
|
||||
}
|
||||
|
||||
// TODO: Implement deleting OverworldItem objects, currently only hides them
|
||||
bool DrawItemEditorPopup(zelda3::overworld::OverworldItem &item) {
|
||||
bool DrawItemEditorPopup(zelda3::OverworldItem &item) {
|
||||
static bool set_done = false;
|
||||
if (set_done) {
|
||||
set_done = false;
|
||||
@@ -351,8 +350,8 @@ bool DrawItemEditorPopup(zelda3::overworld::OverworldItem &item) {
|
||||
BeginChild("ScrollRegion", ImVec2(150, 150), true,
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
ImGui::BeginGroup();
|
||||
for (size_t i = 0; i < zelda3::overworld::kSecretItemNames.size(); i++) {
|
||||
if (Selectable(zelda3::overworld::kSecretItemNames[i].c_str(),
|
||||
for (size_t i = 0; i < zelda3::kSecretItemNames.size(); i++) {
|
||||
if (Selectable(zelda3::kSecretItemNames[i].c_str(),
|
||||
item.id_ == i)) {
|
||||
item.id_ = i;
|
||||
}
|
||||
@@ -489,5 +488,4 @@ bool DrawSpriteEditorPopup(zelda3::Sprite &sprite) {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "app/zelda3/overworld/overworld.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
bool IsMouseHoveringOverEntity(const zelda3::GameEntity &entity,
|
||||
@@ -23,14 +22,14 @@ void HandleEntityDragging(zelda3::GameEntity *entity, ImVec2 canvas_p0,
|
||||
bool free_movement = false);
|
||||
|
||||
bool DrawEntranceInserterPopup();
|
||||
bool DrawOverworldEntrancePopup(zelda3::overworld::OverworldEntrance &entrance);
|
||||
bool DrawOverworldEntrancePopup(zelda3::OverworldEntrance &entrance);
|
||||
|
||||
void DrawExitInserterPopup();
|
||||
bool DrawExitEditorPopup(zelda3::overworld::OverworldExit &exit);
|
||||
bool DrawExitEditorPopup(zelda3::OverworldExit &exit);
|
||||
|
||||
void DrawItemInsertPopup();
|
||||
|
||||
bool DrawItemEditorPopup(zelda3::overworld::OverworldItem &item);
|
||||
bool DrawItemEditorPopup(zelda3::OverworldItem &item);
|
||||
|
||||
enum MyItemColumnID {
|
||||
MyItemColumnID_ID,
|
||||
@@ -81,7 +80,6 @@ void DrawSpriteInserterPopup();
|
||||
bool DrawSpriteEditorPopup(zelda3::Sprite &sprite);
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_OVERWORLD_ENTITY_H
|
||||
|
||||
@@ -15,20 +15,21 @@
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/color.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/gui/style.h"
|
||||
#include "app/gui/zeml.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/common.h"
|
||||
#include "app/zelda3/overworld/overworld.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui_memory_editor.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using core::Renderer;
|
||||
|
||||
using ImGui::BeginChild;
|
||||
using ImGui::BeginTabBar;
|
||||
using ImGui::BeginTabItem;
|
||||
@@ -58,11 +59,11 @@ constexpr int kTile16Size = 0x10;
|
||||
|
||||
absl::Status OverworldEditor::Update() {
|
||||
status_ = absl::OkStatus();
|
||||
if (rom()->is_loaded() && !all_gfx_loaded_) {
|
||||
if (rom_.is_loaded() && !all_gfx_loaded_) {
|
||||
RETURN_IF_ERROR(tile16_editor_.InitBlockset(
|
||||
tile16_blockset_bmp_, current_gfx_bmp_, tile16_individual_,
|
||||
*overworld_.mutable_all_tiles_types()));
|
||||
RETURN_IF_ERROR(LoadEntranceTileTypes(*rom()));
|
||||
ASSIGN_OR_RETURN(entrance_tiletypes_, zelda3::LoadEntranceTileTypes(rom_));
|
||||
all_gfx_loaded_ = true;
|
||||
}
|
||||
|
||||
@@ -96,125 +97,106 @@ void OverworldEditor::DrawToolset() {
|
||||
static bool show_gfx_group = false;
|
||||
static bool show_properties = false;
|
||||
|
||||
if (BeginTable("OWToolset", 22, kToolsetTableFlags, ImVec2(0, 0))) {
|
||||
for (const auto &name : kToolsetColumnNames)
|
||||
ImGui::TableSetupColumn(name.data());
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Button(ICON_MD_UNDO)) {
|
||||
status_ = Undo();
|
||||
}
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Button(ICON_MD_REDO)) {
|
||||
status_ = Redo();
|
||||
}
|
||||
|
||||
TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Button(ICON_MD_ZOOM_OUT)) {
|
||||
ow_map_canvas_.ZoomOut();
|
||||
}
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Button(ICON_MD_ZOOM_IN)) {
|
||||
ow_map_canvas_.ZoomIn();
|
||||
}
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Button(ICON_MD_OPEN_IN_FULL)) {
|
||||
overworld_canvas_fullscreen_ = !overworld_canvas_fullscreen_;
|
||||
}
|
||||
HOVER_HINT("Fullscreen Canvas")
|
||||
|
||||
TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Selectable(ICON_MD_PAN_TOOL_ALT, current_mode == EditingMode::PAN)) {
|
||||
current_mode = EditingMode::PAN;
|
||||
ow_map_canvas_.set_draggable(true);
|
||||
}
|
||||
HOVER_HINT("Pan (Right click and drag)")
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Selectable(ICON_MD_DRAW, current_mode == EditingMode::DRAW_TILE)) {
|
||||
current_mode = EditingMode::DRAW_TILE;
|
||||
}
|
||||
HOVER_HINT("Draw Tile")
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Selectable(ICON_MD_DOOR_FRONT, current_mode == EditingMode::ENTRANCES))
|
||||
current_mode = EditingMode::ENTRANCES;
|
||||
HOVER_HINT("Entrances")
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Selectable(ICON_MD_DOOR_BACK, current_mode == EditingMode::EXITS))
|
||||
current_mode = EditingMode::EXITS;
|
||||
HOVER_HINT("Exits")
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Selectable(ICON_MD_GRASS, current_mode == EditingMode::ITEMS))
|
||||
current_mode = EditingMode::ITEMS;
|
||||
HOVER_HINT("Items")
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Selectable(ICON_MD_PEST_CONTROL_RODENT,
|
||||
current_mode == EditingMode::SPRITES))
|
||||
current_mode = EditingMode::SPRITES;
|
||||
HOVER_HINT("Sprites")
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Selectable(ICON_MD_ADD_LOCATION,
|
||||
current_mode == EditingMode::TRANSPORTS))
|
||||
current_mode = EditingMode::TRANSPORTS;
|
||||
HOVER_HINT("Transports")
|
||||
|
||||
NEXT_COLUMN()
|
||||
if (Selectable(ICON_MD_MUSIC_NOTE, current_mode == EditingMode::MUSIC))
|
||||
current_mode = EditingMode::MUSIC;
|
||||
HOVER_HINT("Music")
|
||||
|
||||
TableNextColumn();
|
||||
if (Button(ICON_MD_GRID_VIEW)) {
|
||||
show_tile16_editor_ = !show_tile16_editor_;
|
||||
}
|
||||
HOVER_HINT("Tile16 Editor")
|
||||
|
||||
TableNextColumn();
|
||||
if (Button(ICON_MD_TABLE_CHART)) {
|
||||
show_gfx_group = !show_gfx_group;
|
||||
}
|
||||
HOVER_HINT("Gfx Group Editor")
|
||||
|
||||
TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
|
||||
|
||||
TableNextColumn();
|
||||
if (Button(ICON_MD_CONTENT_COPY)) {
|
||||
std::vector<uint8_t> png_data;
|
||||
if (gfx::ConvertSurfaceToPNG(maps_bmp_[current_map_].surface(),
|
||||
png_data)) {
|
||||
core::CopyImageToClipboard(png_data);
|
||||
} else {
|
||||
status_ = absl::InternalError(
|
||||
"Failed to convert overworld map surface to PNG");
|
||||
if (toolset_table_.column_contents.empty()) {
|
||||
gui::AddTableColumn(toolset_table_, "##Undo", [&]() {
|
||||
if (Button(ICON_MD_UNDO)) status_ = Undo();
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Redo", [&]() {
|
||||
if (Button(ICON_MD_REDO)) status_ = Redo();
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Sep1", ICON_MD_MORE_VERT);
|
||||
gui::AddTableColumn(toolset_table_, "##ZoomOut", [&]() {
|
||||
if (Button(ICON_MD_ZOOM_OUT)) ow_map_canvas_.ZoomOut();
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##ZoomIn", [&]() {
|
||||
if (Button(ICON_MD_ZOOM_IN)) ow_map_canvas_.ZoomIn();
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Fullscreen", [&]() {
|
||||
if (Button(ICON_MD_OPEN_IN_FULL))
|
||||
overworld_canvas_fullscreen_ = !overworld_canvas_fullscreen_;
|
||||
HOVER_HINT("Fullscreen Canvas")
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Sep2", ICON_MD_MORE_VERT);
|
||||
gui::AddTableColumn(toolset_table_, "##Pan", [&]() {
|
||||
if (Selectable(ICON_MD_PAN_TOOL_ALT, current_mode == EditingMode::PAN)) {
|
||||
current_mode = EditingMode::PAN;
|
||||
ow_map_canvas_.set_draggable(true);
|
||||
}
|
||||
}
|
||||
HOVER_HINT("Copy Map to Clipboard");
|
||||
HOVER_HINT("Pan (Right click and drag)");
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##DrawTile", [&]() {
|
||||
if (Selectable(ICON_MD_DRAW, current_mode == EditingMode::DRAW_TILE)) {
|
||||
current_mode = EditingMode::DRAW_TILE;
|
||||
}
|
||||
HOVER_HINT("Draw Tile");
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Entrances", [&]() {
|
||||
if (Selectable(ICON_MD_DOOR_FRONT,
|
||||
current_mode == EditingMode::ENTRANCES))
|
||||
current_mode = EditingMode::ENTRANCES;
|
||||
HOVER_HINT("Entrances");
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Exits", [&]() {
|
||||
if (Selectable(ICON_MD_DOOR_BACK, current_mode == EditingMode::EXITS))
|
||||
current_mode = EditingMode::EXITS;
|
||||
HOVER_HINT("Exits");
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Items", [&]() {
|
||||
if (Selectable(ICON_MD_GRASS, current_mode == EditingMode::ITEMS))
|
||||
current_mode = EditingMode::ITEMS;
|
||||
HOVER_HINT("Items");
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Sprites", [&]() {
|
||||
if (Selectable(ICON_MD_PEST_CONTROL_RODENT,
|
||||
current_mode == EditingMode::SPRITES))
|
||||
current_mode = EditingMode::SPRITES;
|
||||
HOVER_HINT("Sprites");
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Transports", [&]() {
|
||||
if (Selectable(ICON_MD_ADD_LOCATION,
|
||||
current_mode == EditingMode::TRANSPORTS))
|
||||
current_mode = EditingMode::TRANSPORTS;
|
||||
HOVER_HINT("Transports");
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Music", [&]() {
|
||||
if (Selectable(ICON_MD_MUSIC_NOTE, current_mode == EditingMode::MUSIC))
|
||||
current_mode = EditingMode::MUSIC;
|
||||
HOVER_HINT("Music");
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Tile16Editor", [&]() {
|
||||
if (Button(ICON_MD_GRID_VIEW)) show_tile16_editor_ = !show_tile16_editor_;
|
||||
HOVER_HINT("Tile16 Editor");
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##GfxGroupEditor", [&]() {
|
||||
if (Button(ICON_MD_TABLE_CHART)) show_gfx_group = !show_gfx_group;
|
||||
HOVER_HINT("Gfx Group Editor");
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##sep3", ICON_MD_MORE_VERT);
|
||||
gui::AddTableColumn(toolset_table_, "##Properties", [&]() {
|
||||
if (Button(ICON_MD_CONTENT_COPY)) {
|
||||
std::vector<uint8_t> png_data;
|
||||
if (gfx::ConvertSurfaceToPNG(maps_bmp_[current_map_].surface(),
|
||||
png_data)) {
|
||||
core::CopyImageToClipboard(png_data);
|
||||
} else {
|
||||
status_ = absl::InternalError(
|
||||
"Failed to convert overworld map surface to PNG");
|
||||
}
|
||||
}
|
||||
HOVER_HINT("Copy Map to Clipboard");
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Palette", [&]() {
|
||||
status_ = DisplayPalette(palette_, overworld_.is_loaded());
|
||||
});
|
||||
gui::AddTableColumn(toolset_table_, "##Sep4", ICON_MD_MORE_VERT);
|
||||
gui::AddTableColumn(toolset_table_, "##Properties",
|
||||
[&]() { Checkbox("Properties", &show_properties); });
|
||||
|
||||
TableNextColumn(); // Palette
|
||||
status_ = DisplayPalette(palette_, overworld_.is_loaded());
|
||||
|
||||
TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
|
||||
|
||||
TableNextColumn();
|
||||
Checkbox("Properties", &show_properties);
|
||||
|
||||
ImGui::EndTable();
|
||||
} else {
|
||||
gui::DrawTable(toolset_table_);
|
||||
}
|
||||
|
||||
if (show_tile16_editor_) {
|
||||
// Create a table in ImGui for the Tile16 Editor
|
||||
ImGui::Begin("Tile16 Editor", &show_tile16_editor_,
|
||||
ImGuiWindowFlags_MenuBar);
|
||||
status_ = tile16_editor_.Update();
|
||||
@@ -639,7 +621,7 @@ void OverworldEditor::CheckForMousePan() {
|
||||
|
||||
void OverworldEditor::DrawOverworldCanvas() {
|
||||
if (all_gfx_loaded_) {
|
||||
if (flags()->overworld.kLoadCustomOverworld) {
|
||||
if (core::ExperimentFlags::get().overworld.kLoadCustomOverworld) {
|
||||
DrawCustomOverworldMapSettings();
|
||||
} else {
|
||||
DrawOverworldMapSettings();
|
||||
@@ -724,7 +706,7 @@ void OverworldEditor::DrawTile8Selector() {
|
||||
graphics_bin_canvas_.DrawContextMenu();
|
||||
if (all_gfx_loaded_) {
|
||||
int key = 0;
|
||||
for (auto &value : rom()->gfx_sheets()) {
|
||||
for (auto &value : rom_.gfx_sheets()) {
|
||||
int offset = 0x40 * (key + 1);
|
||||
int top_left_y = graphics_bin_canvas_.zero_point().y + 2;
|
||||
if (key >= 1) {
|
||||
@@ -808,7 +790,7 @@ void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
|
||||
color = ImVec4(255, 255, 255, 200);
|
||||
}
|
||||
ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16, color);
|
||||
std::string str = core::UppercaseHexByte(each.entrance_id_);
|
||||
std::string str = core::HexByte(each.entrance_id_);
|
||||
|
||||
if (current_mode == EditingMode::ENTRANCES) {
|
||||
HandleEntityDragging(&each, canvas_p0, scrolling, is_dragging_entity_,
|
||||
@@ -891,7 +873,7 @@ void OverworldEditor::DrawOverworldExits(ImVec2 canvas_p0, ImVec2 scrolling) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string str = core::UppercaseHexByte(i);
|
||||
std::string str = core::HexByte(i);
|
||||
ow_map_canvas_.DrawText(str, each.x_, each.y_);
|
||||
}
|
||||
i++;
|
||||
@@ -937,8 +919,8 @@ void OverworldEditor::DrawOverworldItems() {
|
||||
}
|
||||
}
|
||||
std::string item_name = "";
|
||||
if (item.id_ < zelda3::overworld::kSecretItemNames.size()) {
|
||||
item_name = zelda3::overworld::kSecretItemNames[item.id_];
|
||||
if (item.id_ < zelda3::kSecretItemNames.size()) {
|
||||
item_name = zelda3::kSecretItemNames[item.id_];
|
||||
} else {
|
||||
item_name = absl::StrFormat("0x%02X", item.id_);
|
||||
}
|
||||
@@ -1027,22 +1009,22 @@ void OverworldEditor::DrawOverworldSprites() {
|
||||
}
|
||||
|
||||
absl::Status OverworldEditor::Save() {
|
||||
if (flags()->overworld.kSaveOverworldMaps) {
|
||||
if (core::ExperimentFlags::get().overworld.kSaveOverworldMaps) {
|
||||
RETURN_IF_ERROR(overworld_.CreateTile32Tilemap());
|
||||
RETURN_IF_ERROR(overworld_.SaveMap32Tiles());
|
||||
RETURN_IF_ERROR(overworld_.SaveMap16Tiles());
|
||||
RETURN_IF_ERROR(overworld_.SaveOverworldMaps());
|
||||
}
|
||||
if (flags()->overworld.kSaveOverworldEntrances) {
|
||||
if (core::ExperimentFlags::get().overworld.kSaveOverworldEntrances) {
|
||||
RETURN_IF_ERROR(overworld_.SaveEntrances());
|
||||
}
|
||||
if (flags()->overworld.kSaveOverworldExits) {
|
||||
if (core::ExperimentFlags::get().overworld.kSaveOverworldExits) {
|
||||
RETURN_IF_ERROR(overworld_.SaveExits());
|
||||
}
|
||||
if (flags()->overworld.kSaveOverworldItems) {
|
||||
if (core::ExperimentFlags::get().overworld.kSaveOverworldItems) {
|
||||
RETURN_IF_ERROR(overworld_.SaveItems());
|
||||
}
|
||||
if (flags()->overworld.kSaveOverworldProperties) {
|
||||
if (core::ExperimentFlags::get().overworld.kSaveOverworldProperties) {
|
||||
RETURN_IF_ERROR(overworld_.SaveMapProperties());
|
||||
}
|
||||
return absl::OkStatus();
|
||||
@@ -1050,7 +1032,7 @@ absl::Status OverworldEditor::Save() {
|
||||
|
||||
absl::Status OverworldEditor::LoadGraphics() {
|
||||
// Load the Link to the Past overworld.
|
||||
RETURN_IF_ERROR(overworld_.Load(*rom()))
|
||||
RETURN_IF_ERROR(overworld_.Load(rom_))
|
||||
palette_ = overworld_.current_area_palette();
|
||||
|
||||
// Create the area graphics image
|
||||
@@ -1066,10 +1048,10 @@ absl::Status OverworldEditor::LoadGraphics() {
|
||||
|
||||
// Copy the tile16 data into individual tiles.
|
||||
auto tile16_data = overworld_.tile16_blockset_data();
|
||||
tile16_individual_.reserve(zelda3::overworld::kNumTile16Individual);
|
||||
tile16_individual_.reserve(zelda3::kNumTile16Individual);
|
||||
|
||||
// Loop through the tiles and copy their pixel data into separate vectors
|
||||
for (uint i = 0; i < zelda3::overworld::kNumTile16Individual; i++) {
|
||||
for (uint i = 0; i < zelda3::kNumTile16Individual; i++) {
|
||||
std::vector<uint8_t> tile_data(kTile16Size * kTile16Size, 0x00);
|
||||
|
||||
// Copy the pixel data for the current tile into the vector
|
||||
@@ -1092,7 +1074,7 @@ absl::Status OverworldEditor::LoadGraphics() {
|
||||
}
|
||||
|
||||
// Render the overworld maps loaded from the ROM.
|
||||
for (int i = 0; i < zelda3::overworld::kNumOverworldMaps; ++i) {
|
||||
for (int i = 0; i < zelda3::kNumOverworldMaps; ++i) {
|
||||
overworld_.set_current_map(i);
|
||||
auto palette = overworld_.current_area_palette();
|
||||
RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
|
||||
@@ -1100,7 +1082,7 @@ absl::Status OverworldEditor::LoadGraphics() {
|
||||
overworld_.current_map_bitmap_data(), maps_bmp_[i], palette));
|
||||
}
|
||||
|
||||
if (flags()->overworld.kDrawOverworldSprites) {
|
||||
if (core::ExperimentFlags::get().overworld.kDrawOverworldSprites) {
|
||||
RETURN_IF_ERROR(LoadSpriteGraphics());
|
||||
}
|
||||
|
||||
@@ -1235,7 +1217,7 @@ absl::Status OverworldEditor::RefreshTile16Blockset() {
|
||||
|
||||
std::vector<std::future<void>> futures;
|
||||
// Loop through the tiles and copy their pixel data into separate vectors
|
||||
for (uint i = 0; i < zelda3::overworld::kNumTile16Individual; i++) {
|
||||
for (uint i = 0; i < zelda3::kNumTile16Individual; i++) {
|
||||
futures.push_back(std::async(
|
||||
std::launch::async,
|
||||
[&](int index) {
|
||||
@@ -1259,7 +1241,7 @@ absl::Status OverworldEditor::RefreshTile16Blockset() {
|
||||
}
|
||||
|
||||
// Render the bitmaps of each tile.
|
||||
for (uint id = 0; id < zelda3::overworld::kNumTile16Individual; id++) {
|
||||
for (uint id = 0; id < zelda3::kNumTile16Individual; id++) {
|
||||
RETURN_IF_ERROR(tile16_individual_[id].ApplyPalette(palette_));
|
||||
Renderer::GetInstance().UpdateBitmap(&tile16_individual_[id]);
|
||||
}
|
||||
@@ -1385,8 +1367,9 @@ absl::Status OverworldEditor::UpdateUsageStats() {
|
||||
if (BeginChild("UnusedSpritesetScroll", ImVec2(0, 0), true,
|
||||
ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||
for (int i = 0; i < 0x81; i++) {
|
||||
auto entrance_name = rom()->resource_label()->GetLabel(
|
||||
"Dungeon Entrance Names", core::UppercaseHexByte(i));
|
||||
auto entrance_name = rom_.resource_label()->CreateOrGetLabel(
|
||||
"Dungeon Entrance Names", core::HexByte(i),
|
||||
zelda3::kEntranceNames[i].data());
|
||||
std::string str = absl::StrFormat("%#x - %s", i, entrance_name);
|
||||
if (Selectable(str.c_str(), selected_entrance_ == i,
|
||||
overworld_.entrances().at(i).deleted
|
||||
@@ -1500,7 +1483,7 @@ void OverworldEditor::DrawDebugWindow() {
|
||||
}
|
||||
}
|
||||
|
||||
void OverworldEditor::InitializeZeml() {
|
||||
void OverworldEditor::Initialize() {
|
||||
// Load zeml string from layouts/overworld.zeml
|
||||
std::string layout = gui::zeml::LoadFile("overworld.zeml");
|
||||
// Parse the zeml string into a Node object
|
||||
@@ -1511,24 +1494,23 @@ void OverworldEditor::InitializeZeml() {
|
||||
gui::zeml::Bind(&*layout_node_.GetNode("OverworldTileSelector"),
|
||||
[this]() { status_ = DrawTileSelector(); });
|
||||
gui::zeml::Bind(&*layout_node_.GetNode("OwUsageStats"), [this]() {
|
||||
if (rom()->is_loaded()) {
|
||||
if (rom_.is_loaded()) {
|
||||
status_ = UpdateUsageStats();
|
||||
}
|
||||
});
|
||||
gui::zeml::Bind(&*layout_node_.GetNode("owToolset"),
|
||||
[this]() { DrawToolset(); });
|
||||
gui::zeml::Bind(&*layout_node_.GetNode("OwTile16Editor"), [this]() {
|
||||
if (rom()->is_loaded()) {
|
||||
if (rom_.is_loaded()) {
|
||||
status_ = tile16_editor_.Update();
|
||||
}
|
||||
});
|
||||
gui::zeml::Bind(&*layout_node_.GetNode("OwGfxGroupEditor"), [this]() {
|
||||
if (rom()->is_loaded()) {
|
||||
if (rom_.is_loaded()) {
|
||||
status_ = gfx_group_editor_.Update();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -1,30 +1,21 @@
|
||||
#ifndef YAZE_APP_EDITOR_OVERWORLDEDITOR_H
|
||||
#define YAZE_APP_EDITOR_OVERWORLDEDITOR_H
|
||||
|
||||
#include <cmath>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/editor/editor.h"
|
||||
#include "app/editor/graphics/gfx_group_editor.h"
|
||||
#include "app/editor/graphics/palette_editor.h"
|
||||
#include "app/editor/graphics/tile16_editor.h"
|
||||
#include "app/editor/overworld/entity.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/gui/zeml.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/overworld/overworld.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
constexpr uint k4BPP = 4;
|
||||
@@ -65,32 +56,6 @@ constexpr absl::string_view kTileSelectorTab = "##TileSelectorTabBar";
|
||||
constexpr absl::string_view kOWEditTable = "##OWEditTable";
|
||||
constexpr absl::string_view kOWMapTable = "#MapSettingsTable";
|
||||
|
||||
constexpr int kEntranceTileTypePtrLow = 0xDB8BF;
|
||||
constexpr int kEntranceTileTypePtrHigh = 0xDB917;
|
||||
constexpr int kNumEntranceTileTypes = 0x2C;
|
||||
|
||||
class EntranceContext {
|
||||
public:
|
||||
absl::Status LoadEntranceTileTypes(Rom& rom) {
|
||||
int offset_low = kEntranceTileTypePtrLow;
|
||||
int offset_high = kEntranceTileTypePtrHigh;
|
||||
|
||||
for (int i = 0; i < kNumEntranceTileTypes; i++) {
|
||||
// Load entrance tile types
|
||||
ASSIGN_OR_RETURN(auto value_low, rom.ReadWord(offset_low + i));
|
||||
entrance_tile_types_low_.push_back(value_low);
|
||||
ASSIGN_OR_RETURN(auto value_high, rom.ReadWord(offset_high + i));
|
||||
entrance_tile_types_low_.push_back(value_high);
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<uint16_t> entrance_tile_types_low_;
|
||||
std::vector<uint16_t> entrance_tile_types_high_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class OverworldEditor
|
||||
* @brief Manipulates the Overworld and OverworldMap data in a Rom.
|
||||
@@ -107,15 +72,11 @@ class EntranceContext {
|
||||
* Provides access to the GfxGroupEditor and Tile16Editor through popup windows.
|
||||
*
|
||||
*/
|
||||
class OverworldEditor : public Editor,
|
||||
public SharedRom,
|
||||
public EntranceContext,
|
||||
public GfxContext,
|
||||
public core::ExperimentFlags {
|
||||
class OverworldEditor : public Editor, public gfx::GfxContext {
|
||||
public:
|
||||
OverworldEditor() { type_ = EditorType::kOverworld; }
|
||||
OverworldEditor(Rom& rom) : rom_(rom) { type_ = EditorType::kOverworld; }
|
||||
|
||||
void InitializeZeml();
|
||||
void Initialize();
|
||||
|
||||
absl::Status Update() final;
|
||||
absl::Status Undo() override { return absl::UnimplementedError("Undo"); }
|
||||
@@ -130,9 +91,6 @@ class OverworldEditor : public Editor,
|
||||
|
||||
auto overworld() { return &overworld_; }
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*/
|
||||
int jump_to_tab() { return jump_to_tab_; }
|
||||
int jump_to_tab_ = -1;
|
||||
|
||||
@@ -281,6 +239,8 @@ class OverworldEditor : public Editor,
|
||||
std::vector<std::vector<uint8_t>> tile8_individual_data_;
|
||||
std::vector<gfx::Bitmap> tile8_individual_;
|
||||
|
||||
Rom& rom_;
|
||||
|
||||
Tile16Editor tile16_editor_;
|
||||
GfxGroupEditor gfx_group_editor_;
|
||||
PaletteEditor palette_editor_;
|
||||
@@ -296,14 +256,15 @@ class OverworldEditor : public Editor,
|
||||
gfx::BitmapTable current_graphics_set_;
|
||||
gfx::BitmapTable sprite_previews_;
|
||||
|
||||
zelda3::overworld::Overworld overworld_;
|
||||
zelda3::OWBlockset refresh_blockset_;
|
||||
zelda3::Overworld overworld_;
|
||||
zelda3::OverworldBlockset refresh_blockset_;
|
||||
|
||||
zelda3::Sprite current_sprite_;
|
||||
|
||||
zelda3::overworld::OverworldEntrance current_entrance_;
|
||||
zelda3::overworld::OverworldExit current_exit_;
|
||||
zelda3::overworld::OverworldItem current_item_;
|
||||
zelda3::OverworldEntrance current_entrance_;
|
||||
zelda3::OverworldExit current_exit_;
|
||||
zelda3::OverworldItem current_item_;
|
||||
zelda3::OverworldEntranceTileTypes entrance_tiletypes_;
|
||||
|
||||
zelda3::GameEntity* current_entity_;
|
||||
zelda3::GameEntity* dragged_entity_;
|
||||
@@ -317,11 +278,15 @@ class OverworldEditor : public Editor,
|
||||
gui::Canvas graphics_bin_canvas_{"GraphicsBin", kGraphicsBinCanvasSize,
|
||||
gui::CanvasGridSize::k16x16};
|
||||
gui::Canvas properties_canvas_;
|
||||
|
||||
gui::Table toolset_table_{"##ToolsetTable0", 22, kToolsetTableFlags};
|
||||
gui::Table map_settings_table_{kOWMapTable.data(), 8, kOWMapFlags,
|
||||
ImVec2(0, 0)};
|
||||
|
||||
gui::zeml::Node layout_node_;
|
||||
absl::Status status_;
|
||||
};
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "app/zelda3/sprite/sprite.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using ImGui::BeginTable;
|
||||
@@ -191,7 +190,7 @@ void SpriteEditor::DrawSpritesList() {
|
||||
int i = 0;
|
||||
for (const auto each_sprite_name : zelda3::kSpriteDefaultNames) {
|
||||
rom()->resource_label()->SelectableLabelWithNameEdit(
|
||||
current_sprite_id_ == i, "Sprite Names", core::UppercaseHexByte(i),
|
||||
current_sprite_id_ == i, "Sprite Names", core::HexByte(i),
|
||||
zelda3::kSpriteDefaultNames[i].data());
|
||||
if (ImGui::IsItemClicked()) {
|
||||
current_sprite_id_ = i;
|
||||
@@ -275,5 +274,4 @@ void SpriteEditor::DrawCustomSpritesMetadata() {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "app/rom.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
constexpr ImGuiTabItemFlags kSpriteTabFlags =
|
||||
@@ -111,7 +110,6 @@ class SpriteEditor : public SharedRom, public Editor {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_SPRITE_EDITOR_H
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
/**
|
||||
* @brief Namespace for the ZSprite format from Zarby's ZSpriteMaker.
|
||||
@@ -390,7 +389,6 @@ struct ZSprite {
|
||||
|
||||
} // namespace zsprite
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_SPRITE_ZSPRITE_H
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
ImGuiKey MapKeyToImGuiKey(char key) {
|
||||
@@ -139,5 +138,4 @@ void CommandManager::LoadKeybindings(const std::string &filepath) {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -8,16 +8,15 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
ImGuiKey MapKeyToImGuiKey(char key);
|
||||
|
||||
class CommandManager {
|
||||
public:
|
||||
public:
|
||||
CommandManager() = default;
|
||||
~CommandManager() = default;
|
||||
|
||||
|
||||
using Command = std::function<void()>;
|
||||
|
||||
struct CommandInfo {
|
||||
@@ -27,7 +26,9 @@ public:
|
||||
std::string desc;
|
||||
CommandInfo(Command command, char mnemonic, const std::string &name,
|
||||
const std::string &desc)
|
||||
: command(std::move(command)), mnemonic(mnemonic), name(name),
|
||||
: command(std::move(command)),
|
||||
mnemonic(mnemonic),
|
||||
name(name),
|
||||
desc(desc) {}
|
||||
CommandInfo() = default;
|
||||
};
|
||||
@@ -72,12 +73,11 @@ public:
|
||||
void SaveKeybindings(const std::string &filepath);
|
||||
void LoadKeybindings(const std::string &filepath);
|
||||
|
||||
private:
|
||||
private:
|
||||
std::unordered_map<std::string, CommandInfoOrPrefix> commands_;
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace editor
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_SYSTEM_COMMAND_MANAGER_H
|
||||
#endif // YAZE_APP_EDITOR_SYSTEM_COMMAND_MANAGER_H
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
class ConstantManager {
|
||||
@@ -27,23 +26,23 @@ class ConstantManager {
|
||||
ImGui::Text("Overworld constants");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("OverworldCustomASMHasBeenApplied: %d",
|
||||
zelda3::overworld::OverworldCustomASMHasBeenApplied);
|
||||
zelda3::OverworldCustomASMHasBeenApplied);
|
||||
ImGui::Text("OverworldCustomAreaSpecificBGPalette: %d",
|
||||
zelda3::overworld::OverworldCustomAreaSpecificBGPalette);
|
||||
zelda3::OverworldCustomAreaSpecificBGPalette);
|
||||
ImGui::Text("OverworldCustomAreaSpecificBGEnabled: %d",
|
||||
zelda3::overworld::OverworldCustomAreaSpecificBGEnabled);
|
||||
zelda3::OverworldCustomAreaSpecificBGEnabled);
|
||||
ImGui::Text("OverworldCustomMainPaletteArray: %d",
|
||||
zelda3::overworld::OverworldCustomMainPaletteArray);
|
||||
zelda3::OverworldCustomMainPaletteArray);
|
||||
ImGui::Text("OverworldCustomMainPaletteEnabled: %d",
|
||||
zelda3::overworld::OverworldCustomMainPaletteEnabled);
|
||||
zelda3::OverworldCustomMainPaletteEnabled);
|
||||
ImGui::Text("OverworldCustomMosaicArray: %d",
|
||||
zelda3::overworld::OverworldCustomMosaicArray);
|
||||
zelda3::OverworldCustomMosaicArray);
|
||||
ImGui::Text("OverworldCustomMosaicEnabled: %d",
|
||||
zelda3::overworld::OverworldCustomMosaicEnabled);
|
||||
zelda3::OverworldCustomMosaicEnabled);
|
||||
ImGui::Text("OverworldCustomAnimatedGFXArray: %d",
|
||||
zelda3::overworld::OverworldCustomAnimatedGFXArray);
|
||||
zelda3::OverworldCustomAnimatedGFXArray);
|
||||
ImGui::Text("OverworldCustomAnimatedGFXEnabled: %d",
|
||||
zelda3::overworld::OverworldCustomAnimatedGFXEnabled);
|
||||
zelda3::OverworldCustomAnimatedGFXEnabled);
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
@@ -71,7 +70,6 @@ class ConstantManager {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_SYSTEM_CONSTANT_MANAGER_H
|
||||
|
||||
@@ -5,13 +5,12 @@
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <system/extension.h>
|
||||
#include <yaze.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
void ExtensionManager::LoadExtension(const std::string& filename,
|
||||
@@ -81,5 +80,4 @@ void ExtensionManager::ExecuteExtensionUI(yaze_editor_context* context) {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
#ifndef YAZE_APP_EDITOR_SYSTEM_EXTENSION_MANAGER_H
|
||||
#define YAZE_APP_EDITOR_SYSTEM_EXTENSION_MANAGER_H
|
||||
|
||||
#include <system/extension.h>
|
||||
#include <yaze.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
class ExtensionManager {
|
||||
@@ -23,7 +22,6 @@ class ExtensionManager {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_SYSTEM_EXTENSION_MANAGER_H
|
||||
|
||||
@@ -5,60 +5,59 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using core::ExperimentFlags;
|
||||
using ImGui::BeginMenu;
|
||||
using ImGui::Checkbox;
|
||||
using ImGui::EndMenu;
|
||||
using ImGui::MenuItem;
|
||||
using ImGui::Separator;
|
||||
|
||||
struct FlagsMenu : public core::ExperimentFlags {
|
||||
struct FlagsMenu {
|
||||
void Draw() {
|
||||
if (BeginMenu("Overworld Flags")) {
|
||||
Checkbox("Enable Overworld Sprites",
|
||||
&mutable_flags()->overworld.kDrawOverworldSprites);
|
||||
&ExperimentFlags::get().overworld.kDrawOverworldSprites);
|
||||
Separator();
|
||||
Checkbox("Save Overworld Maps",
|
||||
&mutable_flags()->overworld.kSaveOverworldMaps);
|
||||
&ExperimentFlags::get().overworld.kSaveOverworldMaps);
|
||||
Checkbox("Save Overworld Entrances",
|
||||
&mutable_flags()->overworld.kSaveOverworldEntrances);
|
||||
&ExperimentFlags::get().overworld.kSaveOverworldEntrances);
|
||||
Checkbox("Save Overworld Exits",
|
||||
&mutable_flags()->overworld.kSaveOverworldExits);
|
||||
&ExperimentFlags::get().overworld.kSaveOverworldExits);
|
||||
Checkbox("Save Overworld Items",
|
||||
&mutable_flags()->overworld.kSaveOverworldItems);
|
||||
&ExperimentFlags::get().overworld.kSaveOverworldItems);
|
||||
Checkbox("Save Overworld Properties",
|
||||
&mutable_flags()->overworld.kSaveOverworldProperties);
|
||||
&ExperimentFlags::get().overworld.kSaveOverworldProperties);
|
||||
Checkbox("Load Custom Overworld",
|
||||
&mutable_flags()->overworld.kLoadCustomOverworld);
|
||||
&ExperimentFlags::get().overworld.kLoadCustomOverworld);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (BeginMenu("Dungeon Flags")) {
|
||||
Checkbox("Draw Dungeon Room Graphics",
|
||||
&mutable_flags()->kDrawDungeonRoomGraphics);
|
||||
&ExperimentFlags::get().kDrawDungeonRoomGraphics);
|
||||
Separator();
|
||||
Checkbox("Save Dungeon Maps", &mutable_flags()->kSaveDungeonMaps);
|
||||
Checkbox("Save Dungeon Maps", &ExperimentFlags::get().kSaveDungeonMaps);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
Checkbox("Use built-in file dialog",
|
||||
&mutable_flags()->kNewFileDialogWrapper);
|
||||
Checkbox("Enable Console Logging", &mutable_flags()->kLogToConsole);
|
||||
&ExperimentFlags::get().kNewFileDialogWrapper);
|
||||
Checkbox("Enable Console Logging", &ExperimentFlags::get().kLogToConsole);
|
||||
Checkbox("Enable Texture Streaming",
|
||||
&mutable_flags()->kLoadTexturesAsStreaming);
|
||||
&ExperimentFlags::get().kLoadTexturesAsStreaming);
|
||||
Checkbox("Log Instructions to Debugger",
|
||||
&mutable_flags()->kLogInstructions);
|
||||
Checkbox("Save All Palettes", &mutable_flags()->kSaveAllPalettes);
|
||||
Checkbox("Save Gfx Groups", &mutable_flags()->kSaveGfxGroups);
|
||||
Checkbox("Save Graphics Sheets", &mutable_flags()->kSaveGraphicsSheet);
|
||||
Checkbox("Use New ImGui Input", &mutable_flags()->kUseNewImGuiInput);
|
||||
&ExperimentFlags::get().kLogInstructions);
|
||||
Checkbox("Save All Palettes", &ExperimentFlags::get().kSaveAllPalettes);
|
||||
Checkbox("Save Gfx Groups", &ExperimentFlags::get().kSaveGfxGroups);
|
||||
Checkbox("Save Graphics Sheets",
|
||||
&ExperimentFlags::get().kSaveGraphicsSheet);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_UTILS_FLAGS_H_
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <vector>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
// System history manager, undo and redo.
|
||||
@@ -26,7 +25,6 @@ class HistoryManager {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_SYSTEM_HISTORY_MANAGER_H
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
PopupManager::PopupManager() {
|
||||
@@ -15,5 +14,5 @@ PopupManager::~PopupManager() {
|
||||
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
|
||||
} // namespace yaze
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define YAZE_APP_EDITOR_POPUP_MANAGER_H
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
// ImGui popup manager.
|
||||
@@ -15,7 +14,7 @@ class PopupManager {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_POPUP_MANAGER_H
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <cstddef>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
// System resource manager.
|
||||
@@ -24,7 +23,6 @@ class ResourceManager {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_SYSTEM_RESOURCE_MANAGER_H
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
using ImGui::BeginChild;
|
||||
@@ -79,5 +78,4 @@ absl::Status SettingsEditor::DrawKeyboardShortcuts() {
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "app/editor/editor.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
// Simple representation for a tree
|
||||
@@ -226,7 +225,6 @@ class SettingsEditor : public Editor {
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_SETTINGS_EDITOR_H_
|
||||
|
||||
@@ -3,19 +3,14 @@
|
||||
#include <SDL.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "app/emu/audio/dsp.h"
|
||||
#include "app/emu/audio/spc700.h"
|
||||
#include "app/emu/cpu/clock.h"
|
||||
#include "app/emu/memory/memory.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace audio {
|
||||
|
||||
static const double apuCyclesPerMaster = (32040 * 32) / (1364 * 262 * 60.0);
|
||||
static const double apuCyclesPerMasterPal = (32040 * 32) / (1364 * 312 * 50.0);
|
||||
@@ -201,7 +196,5 @@ void Apu::SpcWrite(uint16_t adr, uint8_t val) {
|
||||
|
||||
void Apu::SpcIdle(bool waiting) { Cycle(); }
|
||||
|
||||
} // namespace audio
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define YAZE_APP_EMU_APU_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
@@ -11,11 +10,7 @@
|
||||
#include "app/emu/memory/memory.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace audio {
|
||||
|
||||
using namespace memory;
|
||||
|
||||
typedef struct Timer {
|
||||
uint8_t cycles;
|
||||
@@ -93,9 +88,7 @@ class Apu {
|
||||
Spc700 spc700_{callbacks_};
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
#include "app/emu/memory/memory.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace audio {
|
||||
|
||||
static const int rateValues[32] = {0, 2048, 1536, 1280, 1024, 768, 640, 512,
|
||||
384, 320, 256, 192, 160, 128, 96, 80,
|
||||
@@ -631,7 +629,5 @@ void Dsp::GetSamples(int16_t* sample_data, int samples_per_frame,
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
#include "app/emu/memory/memory.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace audio {
|
||||
|
||||
typedef struct DspChannel {
|
||||
// pitch
|
||||
@@ -155,9 +153,7 @@ class Dsp {
|
||||
uint32_t lastFrameBoundary;
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EMU_AUDIO_S_DSP_H
|
||||
#endif // YAZE_APP_EMU_AUDIO_S_DSP_H
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#include "app/emu/audio/spc700.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace audio {
|
||||
|
||||
// adressing modes
|
||||
|
||||
@@ -146,7 +144,5 @@ uint16_t Spc700::addr_plus_i_indexed() {
|
||||
return read(addr) | (read(addr + 1) << 8);
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#include "app/emu/audio/spc700.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace audio {
|
||||
|
||||
// opcode functions
|
||||
|
||||
@@ -481,7 +479,5 @@ void Spc700::SLEEP() {}
|
||||
|
||||
void Spc700::STOP() {}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
@@ -4,14 +4,11 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "app/emu/audio/internal/opcodes.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace audio {
|
||||
|
||||
void Spc700::Reset(bool hard) {
|
||||
if (hard) {
|
||||
@@ -1324,7 +1321,5 @@ void Spc700::LogInstruction(uint16_t initial_pc, uint8_t opcode) {
|
||||
// log_.push_back(log_entry);
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -3,14 +3,11 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace audio {
|
||||
|
||||
/**
|
||||
* @brief AudioRam is an interface for the Audio RAM used by the SPC700.
|
||||
@@ -337,8 +334,7 @@ class Spc700 {
|
||||
// CBNE DBNZ
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
#endif // YAZE_APP_EMU_SPC700_H
|
||||
|
||||
#endif // YAZE_APP_EMU_SPC700_H
|
||||
|
||||
@@ -4,11 +4,10 @@
|
||||
#include <cstdint>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
|
||||
class Clock {
|
||||
public:
|
||||
public:
|
||||
virtual ~Clock() = default;
|
||||
virtual void UpdateClock(double delta) = 0;
|
||||
virtual unsigned long long GetCycleCount() const = 0;
|
||||
@@ -18,23 +17,23 @@ class Clock {
|
||||
};
|
||||
|
||||
class ClockImpl : public Clock {
|
||||
public:
|
||||
public:
|
||||
ClockImpl() = default;
|
||||
virtual ~ClockImpl() = default;
|
||||
|
||||
void UpdateCycleCount(double deltaTime) {
|
||||
accumulatedTime += deltaTime;
|
||||
double cycleTime = 1.0 / frequency;
|
||||
void UpdateCycleCount(double delta_time) {
|
||||
accumulated_time += delta_time;
|
||||
double cycle_time = 1.0 / frequency;
|
||||
|
||||
while (accumulatedTime >= cycleTime) {
|
||||
while (accumulated_time >= cycle_time) {
|
||||
Cycle();
|
||||
accumulatedTime -= cycleTime;
|
||||
accumulated_time -= cycle_time;
|
||||
}
|
||||
}
|
||||
|
||||
void Cycle() {
|
||||
cycle++;
|
||||
cycleCount++;
|
||||
cycle_count++;
|
||||
}
|
||||
|
||||
void UpdateClock(double delta) override {
|
||||
@@ -42,22 +41,21 @@ class ClockImpl : public Clock {
|
||||
ResetAccumulatedTime();
|
||||
}
|
||||
|
||||
void ResetAccumulatedTime() override { accumulatedTime = 0.0; }
|
||||
unsigned long long GetCycleCount() const override { return cycleCount; }
|
||||
void ResetAccumulatedTime() override { accumulated_time = 0.0; }
|
||||
unsigned long long GetCycleCount() const override { return cycle_count; }
|
||||
float GetFrequency() const override { return frequency; }
|
||||
void SetFrequency(float new_frequency) override {
|
||||
this->frequency = new_frequency;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
uint64_t cycle = 0; // Current cycle
|
||||
float frequency = 0.0; // Frequency of the clock in Hz
|
||||
unsigned long long cycleCount = 0; // Total number of cycles executed
|
||||
double accumulatedTime = 0.0; // Accumulated time since the last cycle update
|
||||
unsigned long long cycle_count = 0; // Total number of cycles executed
|
||||
double accumulated_time = 0.0; // Accumulated time since the last cycle update
|
||||
};
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace emu
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EMU_CLOCK_H_
|
||||
#endif // YAZE_APP_EMU_CLOCK_H_
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "app/emu/cpu/internal/opcodes.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
|
||||
void Cpu::Reset(bool hard) {
|
||||
@@ -1804,7 +1803,7 @@ void Cpu::ExecuteInstruction(uint8_t opcode) {
|
||||
|
||||
void Cpu::LogInstructions(uint16_t PC, uint8_t opcode, uint16_t operand,
|
||||
bool immediate, bool accumulator_mode) {
|
||||
if (flags()->kLogInstructions) {
|
||||
if (core::ExperimentFlags::get().kLogInstructions) {
|
||||
std::ostringstream oss;
|
||||
oss << "$" << std::uppercase << std::setw(2) << std::setfill('0')
|
||||
<< static_cast<int>(PB) << ":" << std::hex << PC << ": 0x"
|
||||
@@ -2260,5 +2259,4 @@ uint8_t Cpu::GetInstructionLength(uint8_t opcode) {
|
||||
*/
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "app/emu/memory/memory.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
|
||||
class InstructionEntry {
|
||||
@@ -35,10 +34,9 @@ class InstructionEntry {
|
||||
std::string instruction; // Human-readable instruction text
|
||||
};
|
||||
|
||||
class Cpu : public core::ExperimentFlags {
|
||||
class Cpu {
|
||||
public:
|
||||
explicit Cpu(memory::Memory& mem, Clock& vclock,
|
||||
memory::CpuCallbacks& callbacks)
|
||||
explicit Cpu(Memory& mem, Clock& vclock, CpuCallbacks& callbacks)
|
||||
: memory(mem), clock(vclock), callbacks_(callbacks) {}
|
||||
void Reset(bool hard = false);
|
||||
|
||||
@@ -793,13 +791,13 @@ class Cpu : public core::ExperimentFlags {
|
||||
bool int_wanted_ = false;
|
||||
bool int_delay_ = false;
|
||||
|
||||
memory::CpuCallbacks callbacks_;
|
||||
memory::Memory& memory;
|
||||
CpuCallbacks callbacks_;
|
||||
Memory& memory;
|
||||
Clock& clock;
|
||||
};
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EMU_CPU_H_
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "app/emu/cpu/cpu.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
|
||||
void Cpu::AdrImp() {
|
||||
@@ -186,5 +185,5 @@ uint16_t Cpu::StackRelative() {
|
||||
}
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
|
||||
} // namespace yaze
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "app/emu/cpu/cpu.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
|
||||
/**
|
||||
@@ -398,5 +397,5 @@ void Cpu::ORA(uint32_t low, uint32_t high) {
|
||||
}
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
|
||||
} // namespace yaze
|
||||
@@ -1,6 +1,4 @@
|
||||
#if defined(_WIN32)
|
||||
#define main SDL_main
|
||||
#elif __APPLE__
|
||||
#if __APPLE__
|
||||
#include "app/core/platform/app_delegate.h"
|
||||
#endif
|
||||
|
||||
@@ -10,25 +8,14 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/macros.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/debugging/failure_signal_handler.h"
|
||||
#include "absl/debugging/leak_check.h"
|
||||
#include "absl/debugging/stacktrace.h"
|
||||
#include "absl/debugging/symbolize.h"
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/core/utils/sdl_deleter.h"
|
||||
#include "app/emu/snes.h"
|
||||
#include "app/rom.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui_memory_editor.h"
|
||||
|
||||
using namespace yaze::app;
|
||||
using yaze::app::core::SDL_Deleter;
|
||||
using yaze::core::SDL_Deleter;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
absl::InitializeSymbolizer(argv[0]);
|
||||
@@ -38,6 +25,8 @@ int main(int argc, char **argv) {
|
||||
options.alarm_on_failure_secs = true;
|
||||
absl::InstallFailureSignalHandler(options);
|
||||
|
||||
SDL_SetMainReady();
|
||||
|
||||
std::unique_ptr<SDL_Window, SDL_Deleter> window_;
|
||||
std::unique_ptr<SDL_Renderer, SDL_Deleter> renderer_;
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
|
||||
@@ -96,8 +85,8 @@ int main(int argc, char **argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Rom rom_;
|
||||
emu::SNES snes_;
|
||||
yaze::Rom rom_;
|
||||
yaze::emu::Snes snes_;
|
||||
std::vector<uint8_t> rom_data_;
|
||||
|
||||
bool running = true;
|
||||
@@ -191,10 +180,10 @@ int main(int argc, char **argv) {
|
||||
|
||||
SDL_PauseAudioDevice(audio_device_, 1);
|
||||
SDL_CloseAudioDevice(audio_device_);
|
||||
delete audio_buffer_;
|
||||
// ImGui_ImplSDLRenderer2_Shutdown();
|
||||
// ImGui_ImplSDL2_Shutdown();
|
||||
// ImGui::DestroyContext();
|
||||
delete[] audio_buffer_;
|
||||
//ImGui_ImplSDLRenderer2_Shutdown();
|
||||
//ImGui_ImplSDL2_Shutdown();
|
||||
//ImGui::DestroyContext();
|
||||
SDL_Quit();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
@@ -24,6 +24,7 @@ target_include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src/
|
||||
${PNG_INCLUDE_DIRS}
|
||||
${SDL2_INCLUDE_DIR}
|
||||
${PROJECT_BINARY_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
|
||||
@@ -3,19 +3,15 @@
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "app/core/constants.h"
|
||||
#include "app/core/platform/file_dialog.h"
|
||||
#include "app/core/platform/renderer.h"
|
||||
#include "app/emu/snes.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/gui/zeml.h"
|
||||
#include "app/rom.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui_memory_editor.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
|
||||
namespace {
|
||||
@@ -540,5 +536,5 @@ void Emulator::RenderCpuInstructionLog(
|
||||
}
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
|
||||
} // namespace yaze
|
||||
|
||||
@@ -10,39 +10,13 @@
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
|
||||
/**
|
||||
* @namespace yaze::app::emu
|
||||
* @namespace yaze::emu
|
||||
* @brief SNES Emulation and debugging tools.
|
||||
*/
|
||||
namespace emu {
|
||||
|
||||
// case SDLK_z:
|
||||
// editor.emulator().snes().SetButtonState(1, 0, false);
|
||||
// case SDLK_a:
|
||||
// editor.emulator().snes().SetButtonState(1, 1, false);
|
||||
// case SDLK_RSHIFT:
|
||||
// editor.emulator().snes().SetButtonState(1, 2, false);
|
||||
// case SDLK_RETURN:
|
||||
// editor.emulator().snes().SetButtonState(1, 3, false);
|
||||
// case SDLK_UP:
|
||||
// editor.emulator().snes().SetButtonState(1, 4, false);
|
||||
// case SDLK_DOWN:
|
||||
// editor.emulator().snes().SetButtonState(1, 5, false);
|
||||
// case SDLK_LEFT:
|
||||
// editor.emulator().snes().SetButtonState(1, 6, false);
|
||||
// case SDLK_RIGHT:
|
||||
// editor.emulator().snes().SetButtonState(1, 7, false);
|
||||
// case SDLK_x:
|
||||
// editor.emulator().snes().SetButtonState(1, 8, false);
|
||||
// case SDLK_s:
|
||||
// editor.emulator().snes().SetButtonState(1, 9, false);
|
||||
// case SDLK_d:
|
||||
// editor.emulator().snes().SetButtonState(1, 10, false);
|
||||
// case SDLK_c:
|
||||
// editor.emulator().snes().SetButtonState(1, 11, false);
|
||||
|
||||
struct EmulatorKeybindings {
|
||||
ImGuiKey a_button = ImGuiKey_Z;
|
||||
ImGuiKey b_button = ImGuiKey_A;
|
||||
@@ -134,7 +108,7 @@ class Emulator : public SharedRom {
|
||||
}
|
||||
void Run();
|
||||
|
||||
auto snes() -> SNES& { return snes_; }
|
||||
auto snes() -> Snes& { return snes_; }
|
||||
auto running() const -> bool { return running_; }
|
||||
void set_audio_buffer(int16_t* audio_buffer) { audio_buffer_ = audio_buffer; }
|
||||
auto set_audio_device_id(SDL_AudioDeviceID audio_device) {
|
||||
@@ -179,7 +153,7 @@ class Emulator : public SharedRom {
|
||||
int16_t* audio_buffer_;
|
||||
SDL_AudioDeviceID audio_device_;
|
||||
|
||||
SNES snes_;
|
||||
Snes snes_;
|
||||
SDL_Texture* ppu_texture_;
|
||||
|
||||
std::vector<uint8_t> rom_data_;
|
||||
@@ -190,7 +164,6 @@ class Emulator : public SharedRom {
|
||||
};
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_CORE_EMULATOR_H
|
||||
#endif // YAZE_APP_CORE_EMULATOR_H
|
||||
|
||||
@@ -2,18 +2,14 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "absl/strings/str_split.h"
|
||||
#include "app/emu/cpu/internal/opcodes.h"
|
||||
#include "absl/strings/match.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
|
||||
enum class AddressingMode {
|
||||
@@ -444,5 +440,4 @@ class AsmParser {
|
||||
};
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
#include "app/emu/memory/dma.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace memory {
|
||||
namespace dma {
|
||||
|
||||
static const int bAdrOffsets[8][4] = {{0, 0, 0, 0}, {0, 1, 0, 1}, {0, 0, 0, 0},
|
||||
{0, 0, 1, 1}, {0, 1, 2, 3}, {0, 1, 0, 1},
|
||||
@@ -14,7 +9,7 @@ static const int bAdrOffsets[8][4] = {{0, 0, 0, 0}, {0, 1, 0, 1}, {0, 0, 0, 0},
|
||||
|
||||
static const int transferLength[8] = {1, 2, 2, 4, 4, 4, 2, 4};
|
||||
|
||||
void Reset(MemoryImpl* memory) {
|
||||
void ResetDma(MemoryImpl* memory) {
|
||||
auto channel = memory->dma_channels();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
channel[i].b_addr = 0xff;
|
||||
@@ -41,7 +36,7 @@ void Reset(MemoryImpl* memory) {
|
||||
memory->set_hdma_run_requested(false);
|
||||
}
|
||||
|
||||
uint8_t Read(MemoryImpl* memory, uint16_t adr) {
|
||||
uint8_t ReadDma(MemoryImpl* memory, uint16_t adr) {
|
||||
auto channel = memory->dma_channels();
|
||||
uint8_t c = (adr & 0x70) >> 4;
|
||||
switch (adr & 0xf) {
|
||||
@@ -94,7 +89,7 @@ uint8_t Read(MemoryImpl* memory, uint16_t adr) {
|
||||
}
|
||||
}
|
||||
|
||||
void Write(MemoryImpl* memory, uint16_t adr, uint8_t val) {
|
||||
void WriteDma(MemoryImpl* memory, uint16_t adr, uint8_t val) {
|
||||
auto channel = memory->dma_channels();
|
||||
uint8_t c = (adr & 0x70) >> 4;
|
||||
switch (adr & 0xf) {
|
||||
@@ -158,7 +153,7 @@ void Write(MemoryImpl* memory, uint16_t adr, uint8_t val) {
|
||||
}
|
||||
}
|
||||
|
||||
void DoDma(SNES* snes, MemoryImpl* memory, int cpuCycles) {
|
||||
void DoDma(Snes* snes, MemoryImpl* memory, int cpuCycles) {
|
||||
auto channel = memory->dma_channels();
|
||||
snes->cpu().set_int_delay(true);
|
||||
|
||||
@@ -192,7 +187,7 @@ void DoDma(SNES* snes, MemoryImpl* memory, int cpuCycles) {
|
||||
snes->SyncCycles(false, cpuCycles);
|
||||
}
|
||||
|
||||
void HandleDma(SNES* snes, MemoryImpl* memory, int cpu_cycles) {
|
||||
void HandleDma(Snes* snes, MemoryImpl* memory, int cpu_cycles) {
|
||||
// if hdma triggered, do it, except if dmastate indicates dma will be done now
|
||||
// (it will be done as part of the dma in that case)
|
||||
if (memory->hdma_init_requested() && memory->dma_state() != 2)
|
||||
@@ -210,7 +205,7 @@ void HandleDma(SNES* snes, MemoryImpl* memory, int cpu_cycles) {
|
||||
}
|
||||
}
|
||||
|
||||
void WaitCycle(SNES* snes, MemoryImpl* memory) {
|
||||
void WaitCycle(Snes* snes, MemoryImpl* memory) {
|
||||
// run hdma if requested, no sync (already sycned due to dma)
|
||||
if (memory->hdma_init_requested()) InitHdma(snes, memory, false, 0);
|
||||
if (memory->hdma_run_requested()) DoHdma(snes, memory, false, 0);
|
||||
@@ -218,7 +213,7 @@ void WaitCycle(SNES* snes, MemoryImpl* memory) {
|
||||
snes->RunCycles(8);
|
||||
}
|
||||
|
||||
void InitHdma(SNES* snes, MemoryImpl* memory, bool do_sync, int cpu_cycles) {
|
||||
void InitHdma(Snes* snes, MemoryImpl* memory, bool do_sync, int cpu_cycles) {
|
||||
auto channel = memory->dma_channels();
|
||||
memory->set_hdma_init_requested(false);
|
||||
bool hdmaEnabled = false;
|
||||
@@ -258,7 +253,7 @@ void InitHdma(SNES* snes, MemoryImpl* memory, bool do_sync, int cpu_cycles) {
|
||||
if (do_sync) snes->SyncCycles(false, cpu_cycles);
|
||||
}
|
||||
|
||||
void DoHdma(SNES* snes, MemoryImpl* memory, bool do_sync, int cycles) {
|
||||
void DoHdma(Snes* snes, MemoryImpl* memory, bool do_sync, int cycles) {
|
||||
auto channel = memory->dma_channels();
|
||||
memory->set_hdma_run_requested(false);
|
||||
bool hdmaActive = false;
|
||||
@@ -333,7 +328,7 @@ void DoHdma(SNES* snes, MemoryImpl* memory, bool do_sync, int cycles) {
|
||||
if (do_sync) snes->SyncCycles(false, cycles);
|
||||
}
|
||||
|
||||
void TransferByte(SNES* snes, MemoryImpl* memory, uint16_t aAdr, uint8_t aBank,
|
||||
void TransferByte(Snes* snes, MemoryImpl* memory, uint16_t aAdr, uint8_t aBank,
|
||||
uint8_t bAdr, bool fromB) {
|
||||
// accessing 0x2180 via b-bus while a-bus accesses ram gives open bus
|
||||
bool validB =
|
||||
@@ -369,8 +364,5 @@ void StartDma(MemoryImpl* memory, uint8_t val, bool hdma) {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dma
|
||||
} // namespace memory
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
@@ -7,31 +7,25 @@
|
||||
#include "app/emu/snes.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace memory {
|
||||
namespace dma {
|
||||
|
||||
void Reset(MemoryImpl* memory);
|
||||
void HandleDma(SNES* snes, MemoryImpl* memory, int cpu_cycles);
|
||||
void ResetDma(MemoryImpl* memory);
|
||||
void HandleDma(Snes* snes, MemoryImpl* memory, int cpu_cycles);
|
||||
|
||||
void WaitCycle(SNES* snes, MemoryImpl* memory);
|
||||
void WaitCycle(Snes* snes, MemoryImpl* memory);
|
||||
|
||||
void InitHdma(SNES* snes, MemoryImpl* memory, bool do_sync, int cycles);
|
||||
void DoHdma(SNES* snes, MemoryImpl* memory, bool do_sync, int cycles);
|
||||
void InitHdma(Snes* snes, MemoryImpl* memory, bool do_sync, int cycles);
|
||||
void DoHdma(Snes* snes, MemoryImpl* memory, bool do_sync, int cycles);
|
||||
|
||||
void TransferByte(SNES* snes, MemoryImpl* memory, uint16_t aAdr, uint8_t aBank,
|
||||
void TransferByte(Snes* snes, MemoryImpl* memory, uint16_t aAdr, uint8_t aBank,
|
||||
uint8_t bAdr, bool fromB);
|
||||
|
||||
uint8_t Read(MemoryImpl* memory, uint16_t address);
|
||||
void Write(MemoryImpl* memory, uint16_t address, uint8_t data);
|
||||
uint8_t ReadDma(MemoryImpl* memory, uint16_t address);
|
||||
void WriteDma(MemoryImpl* memory, uint16_t address, uint8_t data);
|
||||
void StartDma(MemoryImpl* memory, uint8_t val, bool hdma);
|
||||
void DoDma(SNES* snes, MemoryImpl* memory, int cycles);
|
||||
void DoDma(Snes* snes, MemoryImpl* memory, int cycles);
|
||||
|
||||
} // namespace dma
|
||||
} // namespace memory
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EMU_MEMORY_DMA_H
|
||||
#endif // YAZE_APP_EMU_MEMORY_DMA_H
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#ifndef YAZE_APP_EMU_MEMORY_DMA_CHANNEL_H
|
||||
#define YAZE_APP_EMU_MEMORY_DMA_CHANNEL_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace memory {
|
||||
|
||||
typedef struct DmaChannel {
|
||||
uint8_t b_addr;
|
||||
uint16_t a_addr;
|
||||
uint8_t a_bank;
|
||||
uint16_t size; // also indirect hdma adr
|
||||
uint8_t ind_bank; // hdma
|
||||
uint16_t table_addr; // hdma
|
||||
uint8_t rep_count; // hdma
|
||||
uint8_t unusedByte;
|
||||
bool dma_active;
|
||||
bool hdma_active;
|
||||
uint8_t mode;
|
||||
bool fixed;
|
||||
bool decrement;
|
||||
bool indirect; // hdma
|
||||
bool from_b;
|
||||
bool unusedBit;
|
||||
bool do_transfer; // hdma
|
||||
bool terminated; // hdma
|
||||
} DmaChannel;
|
||||
|
||||
} // namespace memory
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EMU_MEMORY_DMA_CHANNEL_H
|
||||
@@ -1,16 +1,10 @@
|
||||
#include "app/emu/memory/memory.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace memory {
|
||||
|
||||
void MemoryImpl::Initialize(const std::vector<uint8_t>& rom_data,
|
||||
bool verbose) {
|
||||
@@ -23,13 +17,9 @@ void MemoryImpl::Initialize(const std::vector<uint8_t>& rom_data,
|
||||
rom_.resize(rom_size_);
|
||||
|
||||
// Copy memory into rom_
|
||||
for (size_t i = 0; i < rom_size_; i++) {
|
||||
rom_[i] = rom_data[i];
|
||||
}
|
||||
std::copy(rom_data.begin(), rom_data.begin() + rom_size_, rom_.begin());
|
||||
ram_.resize(sram_size_);
|
||||
for (size_t i = 0; i < sram_size_; i++) {
|
||||
ram_[i] = 0;
|
||||
}
|
||||
std::fill(ram_.begin(), ram_.end(), 0);
|
||||
|
||||
// Clear memory
|
||||
memory_.resize(0x1000000); // 16 MB
|
||||
@@ -165,7 +155,5 @@ uint32_t MemoryImpl::GetMappedAddress(uint32_t address) const {
|
||||
return address; // Return the original address if no mapping is defined
|
||||
}
|
||||
|
||||
} // namespace memory
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
#ifndef MEM_H
|
||||
#define MEM_H
|
||||
#ifndef YAZE_APP_EMU_MEMORY_H
|
||||
#define YAZE_APP_EMU_MEMORY_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "app/emu/memory/dma_channel.h"
|
||||
|
||||
// LoROM (Mode 20):
|
||||
|
||||
// Banks Offset Purpose
|
||||
@@ -27,9 +24,28 @@
|
||||
// 7F 0000-FFFF System RAM
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace memory {
|
||||
|
||||
typedef struct DmaChannel {
|
||||
uint8_t b_addr;
|
||||
uint16_t a_addr;
|
||||
uint8_t a_bank;
|
||||
uint16_t size; // also indirect hdma adr
|
||||
uint8_t ind_bank; // hdma
|
||||
uint16_t table_addr; // hdma
|
||||
uint8_t rep_count; // hdma
|
||||
uint8_t unusedByte;
|
||||
bool dma_active;
|
||||
bool hdma_active;
|
||||
uint8_t mode;
|
||||
bool fixed;
|
||||
bool decrement;
|
||||
bool indirect; // hdma
|
||||
bool from_b;
|
||||
bool unusedBit;
|
||||
bool do_transfer; // hdma
|
||||
bool terminated; // hdma
|
||||
} DmaChannel;
|
||||
|
||||
typedef struct CpuCallbacks {
|
||||
std::function<uint8_t(uint32_t)> read_byte;
|
||||
@@ -46,7 +62,7 @@ constexpr uint32_t kRAMSize = 0x20000;
|
||||
* @brief Memory interface
|
||||
*/
|
||||
class Memory {
|
||||
public:
|
||||
public:
|
||||
virtual ~Memory() = default;
|
||||
virtual uint8_t ReadByte(uint32_t address) const = 0;
|
||||
virtual uint16_t ReadWord(uint32_t address) const = 0;
|
||||
@@ -100,25 +116,25 @@ class Memory {
|
||||
*
|
||||
*/
|
||||
class MemoryImpl : public Memory {
|
||||
public:
|
||||
void Initialize(const std::vector<uint8_t>& romData, bool verbose = false);
|
||||
public:
|
||||
void Initialize(const std::vector<uint8_t> &romData, bool verbose = false);
|
||||
|
||||
uint16_t GetHeaderOffset() {
|
||||
uint16_t offset;
|
||||
switch (memory_[(0x00 << 16) + 0xFFD5] & 0x07) {
|
||||
case 0: // LoROM
|
||||
offset = 0x7FC0;
|
||||
break;
|
||||
case 1: // HiROM
|
||||
offset = 0xFFC0;
|
||||
break;
|
||||
case 5: // ExHiROM
|
||||
offset = 0x40;
|
||||
break;
|
||||
default:
|
||||
throw std::invalid_argument(
|
||||
"Unable to locate supported ROM mapping mode in the provided ROM "
|
||||
"file. Please try another ROM file.");
|
||||
case 0: // LoROM
|
||||
offset = 0x7FC0;
|
||||
break;
|
||||
case 1: // HiROM
|
||||
offset = 0xFFC0;
|
||||
break;
|
||||
case 5: // ExHiROM
|
||||
offset = 0x40;
|
||||
break;
|
||||
default:
|
||||
throw std::invalid_argument(
|
||||
"Unable to locate supported ROM mapping mode in the provided ROM "
|
||||
"file. Please try another ROM file.");
|
||||
}
|
||||
|
||||
return offset;
|
||||
@@ -221,7 +237,7 @@ class MemoryImpl : public Memory {
|
||||
|
||||
// Stack Pointer access.
|
||||
uint16_t SP() const override { return SP_; }
|
||||
auto mutable_sp() -> uint16_t& { return SP_; }
|
||||
auto mutable_sp() -> uint16_t & { return SP_; }
|
||||
void SetSP(uint16_t value) override { SP_ = value; }
|
||||
void ClearMemory() override { std::fill(memory_.begin(), memory_.end(), 0); }
|
||||
|
||||
@@ -261,15 +277,15 @@ class MemoryImpl : public Memory {
|
||||
auto v_pos() const -> uint16_t override { return v_pos_; }
|
||||
auto pal_timing() const -> bool override { return pal_timing_; }
|
||||
|
||||
auto dma_state() -> uint8_t& { return dma_state_; }
|
||||
auto dma_state() -> uint8_t & { return dma_state_; }
|
||||
void set_dma_state(uint8_t value) { dma_state_ = value; }
|
||||
auto dma_channels() -> DmaChannel* { return channel; }
|
||||
auto dma_channels() -> DmaChannel * { return channel; }
|
||||
|
||||
// Define memory regions
|
||||
std::vector<uint8_t> rom_;
|
||||
std::vector<uint8_t> ram_;
|
||||
|
||||
private:
|
||||
private:
|
||||
uint32_t GetMappedAddress(uint32_t address) const;
|
||||
|
||||
bool verbose_ = false;
|
||||
@@ -307,9 +323,7 @@ class MemoryImpl : public Memory {
|
||||
std::vector<uint8_t> memory_;
|
||||
};
|
||||
|
||||
} // namespace memory
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace emu
|
||||
} // namespace yaze
|
||||
|
||||
#endif // MEM_H
|
||||
#endif // YAZE_APP_EMU_MEMORY_H
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
#include "app/emu/snes.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "app/emu/audio/apu.h"
|
||||
#include "app/emu/audio/spc700.h"
|
||||
#include "app/emu/cpu/clock.h"
|
||||
#include "app/emu/cpu/cpu.h"
|
||||
#include "app/emu/memory/dma.h"
|
||||
#include "app/emu/memory/memory.h"
|
||||
#include "app/emu/video/ppu.h"
|
||||
#include "app/rom.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
|
||||
namespace {
|
||||
@@ -33,7 +25,7 @@ uint8_t input_read(Input* input) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void SNES::Init(std::vector<uint8_t>& rom_data) {
|
||||
void Snes::Init(std::vector<uint8_t>& rom_data) {
|
||||
// Initialize the CPU, PPU, and APU
|
||||
ppu_.Init();
|
||||
apu_.Init();
|
||||
@@ -45,11 +37,11 @@ void SNES::Init(std::vector<uint8_t>& rom_data) {
|
||||
running_ = true;
|
||||
}
|
||||
|
||||
void SNES::Reset(bool hard) {
|
||||
void Snes::Reset(bool hard) {
|
||||
cpu_.Reset(hard);
|
||||
apu_.Reset();
|
||||
ppu_.Reset();
|
||||
memory::dma::Reset(&memory_);
|
||||
ResetDma(&memory_);
|
||||
input1.latch_line_ = false;
|
||||
input2.latch_line_ = false;
|
||||
input1.latched_state_ = 0;
|
||||
@@ -85,7 +77,7 @@ void SNES::Reset(bool hard) {
|
||||
InitAccessTime(false);
|
||||
}
|
||||
|
||||
void SNES::RunFrame() {
|
||||
void Snes::RunFrame() {
|
||||
while (in_vblank_) {
|
||||
cpu_.RunOpcode();
|
||||
}
|
||||
@@ -95,9 +87,9 @@ void SNES::RunFrame() {
|
||||
}
|
||||
}
|
||||
|
||||
void SNES::CatchUpApu() { apu_.RunCycles(cycles_); }
|
||||
void Snes::CatchUpApu() { apu_.RunCycles(cycles_); }
|
||||
|
||||
void SNES::HandleInput() {
|
||||
void Snes::HandleInput() {
|
||||
memset(port_auto_read_, 0, sizeof(port_auto_read_));
|
||||
// latch controllers
|
||||
input_latch(&input1, true);
|
||||
@@ -114,7 +106,7 @@ void SNES::HandleInput() {
|
||||
}
|
||||
}
|
||||
|
||||
void SNES::RunCycle() {
|
||||
void Snes::RunCycle() {
|
||||
cycles_ += 2;
|
||||
|
||||
// check for h/v timer irq's
|
||||
@@ -229,7 +221,7 @@ void SNES::RunCycle() {
|
||||
if (auto_joy_timer_ > 0) auto_joy_timer_ -= 2;
|
||||
}
|
||||
|
||||
void SNES::RunCycles(int cycles) {
|
||||
void Snes::RunCycles(int cycles) {
|
||||
if (memory_.h_pos() + cycles >= 536 && memory_.h_pos() < 536) {
|
||||
// if we go past 536, add 40 cycles for dram refersh
|
||||
cycles += 40;
|
||||
@@ -239,7 +231,7 @@ void SNES::RunCycles(int cycles) {
|
||||
}
|
||||
}
|
||||
|
||||
void SNES::SyncCycles(bool start, int sync_cycles) {
|
||||
void Snes::SyncCycles(bool start, int sync_cycles) {
|
||||
int count = 0;
|
||||
if (start) {
|
||||
sync_cycle_ = cycles_;
|
||||
@@ -250,7 +242,7 @@ void SNES::SyncCycles(bool start, int sync_cycles) {
|
||||
RunCycles(count);
|
||||
}
|
||||
|
||||
uint8_t SNES::ReadBBus(uint8_t adr) {
|
||||
uint8_t Snes::ReadBBus(uint8_t adr) {
|
||||
if (adr < 0x40) {
|
||||
return ppu_.Read(adr, ppu_latch_);
|
||||
}
|
||||
@@ -266,7 +258,7 @@ uint8_t SNES::ReadBBus(uint8_t adr) {
|
||||
return memory_.open_bus();
|
||||
}
|
||||
|
||||
uint8_t SNES::ReadReg(uint16_t adr) {
|
||||
uint8_t Snes::ReadReg(uint16_t adr) {
|
||||
switch (adr) {
|
||||
case 0x4210: {
|
||||
uint8_t val = 0x2; // CPU version (4 bit)
|
||||
@@ -319,7 +311,7 @@ uint8_t SNES::ReadReg(uint16_t adr) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t SNES::Rread(uint32_t adr) {
|
||||
uint8_t Snes::Rread(uint32_t adr) {
|
||||
uint8_t bank = adr >> 16;
|
||||
adr &= 0xffff;
|
||||
if (bank == 0x7e || bank == 0x7f) {
|
||||
@@ -342,20 +334,20 @@ uint8_t SNES::Rread(uint32_t adr) {
|
||||
return ReadReg(adr); // internal registers
|
||||
}
|
||||
if (adr >= 0x4300 && adr < 0x4380) {
|
||||
return memory::dma::Read(&memory_, adr); // dma registers
|
||||
return ReadDma(&memory_, adr); // dma registers
|
||||
}
|
||||
}
|
||||
// read from cart
|
||||
return memory_.cart_read(bank, adr);
|
||||
}
|
||||
|
||||
uint8_t SNES::Read(uint32_t adr) {
|
||||
uint8_t Snes::Read(uint32_t adr) {
|
||||
uint8_t val = Rread(adr);
|
||||
memory_.set_open_bus(val);
|
||||
return val;
|
||||
}
|
||||
|
||||
void SNES::WriteBBus(uint8_t adr, uint8_t val) {
|
||||
void Snes::WriteBBus(uint8_t adr, uint8_t val) {
|
||||
if (adr < 0x40) {
|
||||
ppu_.Write(adr, val);
|
||||
return;
|
||||
@@ -386,7 +378,7 @@ void SNES::WriteBBus(uint8_t adr, uint8_t val) {
|
||||
}
|
||||
}
|
||||
|
||||
void SNES::WriteReg(uint16_t adr, uint8_t val) {
|
||||
void Snes::WriteReg(uint16_t adr, uint8_t val) {
|
||||
switch (adr) {
|
||||
case 0x4200: {
|
||||
auto_joy_read_ = val & 0x1;
|
||||
@@ -456,11 +448,11 @@ void SNES::WriteReg(uint16_t adr, uint8_t val) {
|
||||
break;
|
||||
}
|
||||
case 0x420b: {
|
||||
memory::dma::StartDma(&memory_, val, false);
|
||||
StartDma(&memory_, val, false);
|
||||
break;
|
||||
}
|
||||
case 0x420c: {
|
||||
memory::dma::StartDma(&memory_, val, true);
|
||||
StartDma(&memory_, val, true);
|
||||
break;
|
||||
}
|
||||
case 0x420d: {
|
||||
@@ -473,7 +465,7 @@ void SNES::WriteReg(uint16_t adr, uint8_t val) {
|
||||
}
|
||||
}
|
||||
|
||||
void SNES::Write(uint32_t adr, uint8_t val) {
|
||||
void Snes::Write(uint32_t adr, uint8_t val) {
|
||||
memory_.set_open_bus(val);
|
||||
uint8_t bank = adr >> 16;
|
||||
adr &= 0xffff;
|
||||
@@ -495,7 +487,7 @@ void SNES::Write(uint32_t adr, uint8_t val) {
|
||||
WriteReg(adr, val); // internal registers
|
||||
}
|
||||
if (adr >= 0x4300 && adr < 0x4380) {
|
||||
memory::dma::Write(&memory_, adr, val); // dma registers
|
||||
WriteDma(&memory_, adr, val); // dma registers
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,7 +495,7 @@ void SNES::Write(uint32_t adr, uint8_t val) {
|
||||
memory_.cart_write(bank, adr, val);
|
||||
}
|
||||
|
||||
int SNES::GetAccessTime(uint32_t adr) {
|
||||
int Snes::GetAccessTime(uint32_t adr) {
|
||||
uint8_t bank = adr >> 16;
|
||||
adr &= 0xffff;
|
||||
if ((bank < 0x40 || (bank >= 0x80 && bank < 0xc0)) && adr < 0x8000) {
|
||||
@@ -517,38 +509,38 @@ int SNES::GetAccessTime(uint32_t adr) {
|
||||
: 8; // depends on setting in banks 80+
|
||||
}
|
||||
|
||||
uint8_t SNES::CpuRead(uint32_t adr) {
|
||||
uint8_t Snes::CpuRead(uint32_t adr) {
|
||||
cpu_.set_int_delay(false);
|
||||
const int cycles = access_time[adr] - 4;
|
||||
memory::dma::HandleDma(this, &memory_, cycles);
|
||||
HandleDma(this, &memory_, cycles);
|
||||
RunCycles(cycles);
|
||||
uint8_t rv = Read(adr);
|
||||
memory::dma::HandleDma(this, &memory_, 4);
|
||||
HandleDma(this, &memory_, 4);
|
||||
RunCycles(4);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void SNES::CpuWrite(uint32_t adr, uint8_t val) {
|
||||
void Snes::CpuWrite(uint32_t adr, uint8_t val) {
|
||||
cpu_.set_int_delay(false);
|
||||
const int cycles = access_time[adr];
|
||||
memory::dma::HandleDma(this, &memory_, cycles);
|
||||
HandleDma(this, &memory_, cycles);
|
||||
RunCycles(cycles);
|
||||
Write(adr, val);
|
||||
}
|
||||
|
||||
void SNES::CpuIdle(bool waiting) {
|
||||
void Snes::CpuIdle(bool waiting) {
|
||||
cpu_.set_int_delay(false);
|
||||
memory::dma::HandleDma(this, &memory_, 6);
|
||||
HandleDma(this, &memory_, 6);
|
||||
RunCycles(6);
|
||||
}
|
||||
|
||||
void SNES::SetSamples(int16_t* sample_data, int wanted_samples) {
|
||||
void Snes::SetSamples(int16_t* sample_data, int wanted_samples) {
|
||||
apu_.dsp().GetSamples(sample_data, wanted_samples, memory_.pal_timing());
|
||||
}
|
||||
|
||||
void SNES::SetPixels(uint8_t* pixel_data) { ppu_.PutPixels(pixel_data); }
|
||||
void Snes::SetPixels(uint8_t* pixel_data) { ppu_.PutPixels(pixel_data); }
|
||||
|
||||
void SNES::SetButtonState(int player, int button, bool pressed) {
|
||||
void Snes::SetButtonState(int player, int button, bool pressed) {
|
||||
// set key in controller
|
||||
if (player == 1) {
|
||||
if (pressed) {
|
||||
@@ -565,7 +557,7 @@ void SNES::SetButtonState(int player, int button, bool pressed) {
|
||||
}
|
||||
}
|
||||
|
||||
void SNES::InitAccessTime(bool recalc) {
|
||||
void Snes::InitAccessTime(bool recalc) {
|
||||
int start = (recalc) ? 0x800000 : 0; // recalc only updates fast rom
|
||||
access_time.resize(0x1000000);
|
||||
for (int i = start; i < 0x1000000; i++) {
|
||||
@@ -574,5 +566,4 @@ void SNES::InitAccessTime(bool recalc) {
|
||||
}
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
@@ -10,22 +10,20 @@
|
||||
#include "app/emu/video/ppu.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
|
||||
struct Input {
|
||||
uint8_t type;
|
||||
// latchline
|
||||
bool latch_line_;
|
||||
// for controller
|
||||
uint16_t current_state_; // actual state
|
||||
uint16_t latched_state_;
|
||||
};
|
||||
|
||||
class SNES {
|
||||
class Snes {
|
||||
public:
|
||||
SNES() = default;
|
||||
~SNES() = default;
|
||||
Snes() = default;
|
||||
~Snes() = default;
|
||||
|
||||
// Initialization
|
||||
void Init(std::vector<uint8_t>& rom_data);
|
||||
@@ -62,9 +60,9 @@ class SNES {
|
||||
void SetButtonState(int player, int button, bool pressed);
|
||||
bool running() const { return running_; }
|
||||
auto cpu() -> Cpu& { return cpu_; }
|
||||
auto ppu() -> video::Ppu& { return ppu_; }
|
||||
auto apu() -> audio::Apu& { return apu_; }
|
||||
auto Memory() -> memory::MemoryImpl& { return memory_; }
|
||||
auto ppu() -> Ppu& { return ppu_; }
|
||||
auto apu() -> Apu& { return apu_; }
|
||||
auto Memory() -> MemoryImpl& { return memory_; }
|
||||
auto get_ram() -> uint8_t* { return ram; }
|
||||
auto mutable_cycles() -> uint64_t& { return cycles_; }
|
||||
void InitAccessTime(bool recalc);
|
||||
@@ -74,16 +72,16 @@ class SNES {
|
||||
private:
|
||||
// Components of the SNES
|
||||
ClockImpl clock_;
|
||||
memory::MemoryImpl memory_;
|
||||
MemoryImpl memory_;
|
||||
|
||||
memory::CpuCallbacks cpu_callbacks_ = {
|
||||
CpuCallbacks cpu_callbacks_ = {
|
||||
[&](uint32_t adr) { return CpuRead(adr); },
|
||||
[&](uint32_t adr, uint8_t val) { CpuWrite(adr, val); },
|
||||
[&](bool waiting) { CpuIdle(waiting); },
|
||||
};
|
||||
Cpu cpu_{memory_, clock_, cpu_callbacks_};
|
||||
video::Ppu ppu_{memory_, clock_};
|
||||
audio::Apu apu_{memory_};
|
||||
Ppu ppu_{memory_, clock_};
|
||||
Apu apu_{memory_};
|
||||
|
||||
// Currently loaded ROM
|
||||
std::vector<uint8_t> rom_data;
|
||||
@@ -131,7 +129,7 @@ class SNES {
|
||||
};
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EMU_SNES_H
|
||||
|
||||
@@ -7,11 +7,7 @@
|
||||
#include "app/emu/memory/memory.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace video {
|
||||
|
||||
using namespace PpuRegisters;
|
||||
|
||||
// array for layer definitions per mode:
|
||||
// 0-7: mode 0-7; 8: mode 1 + l3prio; 9: mode 7 + extbg
|
||||
@@ -1054,7 +1050,5 @@ void Ppu::PutPixels(uint8_t* pixels) {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace video
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -11,12 +11,7 @@
|
||||
#include "app/rom.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace video {
|
||||
|
||||
using namespace PpuRegisters;
|
||||
using namespace memory;
|
||||
|
||||
class PpuInterface {
|
||||
public:
|
||||
@@ -259,7 +254,7 @@ struct BackgroundLayer {
|
||||
class Ppu : public SharedRom {
|
||||
public:
|
||||
// Initializes the PPU with the necessary resources and dependencies
|
||||
Ppu(memory::Memory& memory, Clock& clock) : memory_(memory), clock_(clock) {}
|
||||
Ppu(Memory& memory, Clock& clock) : memory_(memory), clock_(clock) {}
|
||||
|
||||
// Initialize the frame buffer
|
||||
void Init() {
|
||||
@@ -456,9 +451,7 @@ class Ppu : public SharedRom {
|
||||
std::array<BGVOFS, 4> bgvofs_;
|
||||
};
|
||||
|
||||
} // namespace video
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EMU_PPU_H
|
||||
#endif // YAZE_APP_EMU_PPU_H
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
#ifndef YAZE_APP_EMU_VIDEO_PPU_REGISTERS_H
|
||||
#define YAZE_APP_EMU_VIDEO_PPU_REGISTERS_H
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace emu {
|
||||
namespace video {
|
||||
namespace PpuRegisters {
|
||||
|
||||
constexpr uint16_t INIDISP = 0x2100;
|
||||
|
||||
@@ -413,10 +408,7 @@ struct STAT78 {
|
||||
uint8_t unused : 1;
|
||||
};
|
||||
|
||||
} // namespace PpuRegisters
|
||||
} // namespace video
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EMU_VIDEO_PPU_REGISTERS_H
|
||||
#endif // YAZE_APP_EMU_VIDEO_PPU_REGISTERS_H
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
}
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace gfx {
|
||||
|
||||
using core::SDL_Surface_Deleter;
|
||||
@@ -437,9 +436,8 @@ void Bitmap::Get8x8Tile(int tile_index, int x, int y,
|
||||
int tile_x = (x * 8) % width_;
|
||||
int tile_y = (y * 8) % height_;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int row_offset = tile_offset + ((tile_y + i) * width_);
|
||||
for (int j = 0; j < 8; j++) {
|
||||
int pixel_offset = row_offset + (tile_x + j);
|
||||
int pixel_offset = tile_offset + (tile_y + i) * width_ + tile_x + j;
|
||||
int pixel_value = data_[pixel_offset];
|
||||
tile_data[tile_data_offset] = pixel_value;
|
||||
tile_data_offset++;
|
||||
@@ -478,9 +476,11 @@ void Bitmap::WriteColor(int position, const ImVec4 &color) {
|
||||
|
||||
// Write the color index to the pixel data
|
||||
pixel_data_[position] = index;
|
||||
data_[position] = ConvertRgbToSnes(color);
|
||||
|
||||
modified_ = true;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace app
|
||||
|
||||
} // namespace yaze
|
||||
|
||||
@@ -12,10 +12,9 @@
|
||||
#include "app/gfx/snes_palette.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
|
||||
/**
|
||||
* @namespace yaze::app::gfx
|
||||
* @namespace yaze::gfx
|
||||
* @brief Contains classes for handling graphical data.
|
||||
*/
|
||||
namespace gfx {
|
||||
@@ -214,7 +213,7 @@ class Bitmap {
|
||||
using BitmapTable = std::unordered_map<int, gfx::Bitmap>;
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace app
|
||||
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_GFX_BITMAP_H
|
||||
|
||||
@@ -6,19 +6,299 @@
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "app/core/constants.h"
|
||||
#include "app/rom.h"
|
||||
|
||||
#define DEBUG_LOG(msg) std::cout << msg << std::endl
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace gfx {
|
||||
|
||||
namespace lc_lz2 {
|
||||
std::vector<uint8_t> HyruleMagicCompress(uint8_t const* const src,
|
||||
int const oldsize, int* const size,
|
||||
int const flag) {
|
||||
unsigned char* b2 =
|
||||
(unsigned char*)malloc(0x1000); // allocate a 2^12 sized buffer
|
||||
|
||||
// Compression commands
|
||||
int i, j, k, l, m = 0, n, o = 0, bd = 0, p, q = 0, r;
|
||||
|
||||
for (i = 0; i < oldsize;) {
|
||||
l = src[i]; // grab a char from the buffer.
|
||||
|
||||
k = 0;
|
||||
|
||||
r = !!q; // r = the same logical value (0 or 1) as q, but not the same
|
||||
// value necesarily.
|
||||
|
||||
for (j = 0; j < i - 1; j++) {
|
||||
if (src[j] == l) {
|
||||
m = oldsize - j;
|
||||
|
||||
for (n = 0; n < m; n++)
|
||||
if (src[n + j] != src[n + i]) break;
|
||||
|
||||
if (n > k) k = n, o = j;
|
||||
}
|
||||
}
|
||||
|
||||
for (n = i + 1; n < oldsize; n++) {
|
||||
if (src[n] != l) {
|
||||
// look for chars identical to the first one.
|
||||
// stop if we can't find one.
|
||||
// n will reach i+k+1 for some k >= 0.
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
n -= i; // offset back by i. i.e. n = k+1 as above.
|
||||
|
||||
if (n > 1 + r)
|
||||
p = 1;
|
||||
else {
|
||||
m = src[i + 1];
|
||||
|
||||
for (n = i + 2; n < oldsize; n++) {
|
||||
if (src[n] != l) break;
|
||||
|
||||
n++;
|
||||
|
||||
if (src[n] != m) break;
|
||||
}
|
||||
|
||||
n -= i;
|
||||
|
||||
if (n > 2 + r)
|
||||
p = 2;
|
||||
else {
|
||||
m = oldsize - i;
|
||||
|
||||
for (n = 1; n < m; n++)
|
||||
if (src[i + n] != l + n) break;
|
||||
|
||||
if (n > 1 + r)
|
||||
p = 3;
|
||||
else
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (k > 3 + r && k > n + (p & 1)) p = 4, n = k;
|
||||
|
||||
if (!p)
|
||||
q++, i++;
|
||||
else {
|
||||
if (q) {
|
||||
q--;
|
||||
|
||||
if (q > 31) {
|
||||
b2[bd++] = (unsigned char)(224 + (q >> 8));
|
||||
}
|
||||
|
||||
b2[bd++] = (unsigned char)q;
|
||||
q++;
|
||||
|
||||
memcpy(b2 + bd, src + i - q, q);
|
||||
|
||||
bd += q;
|
||||
q = 0;
|
||||
}
|
||||
|
||||
i += n;
|
||||
n--;
|
||||
|
||||
if (n > 31) {
|
||||
b2[bd++] = (unsigned char)(224 + (n >> 8) + (p << 2));
|
||||
b2[bd++] = (unsigned char)n;
|
||||
} else
|
||||
b2[bd++] = (unsigned char)((p << 5) + n);
|
||||
|
||||
switch (p) {
|
||||
case 1:
|
||||
case 3:
|
||||
b2[bd++] = (unsigned char)l;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
b2[bd++] = (unsigned char)l;
|
||||
b2[bd++] = (unsigned char)m;
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (flag) {
|
||||
b2[bd++] = (unsigned char)(o >> 8);
|
||||
b2[bd++] = (unsigned char)o;
|
||||
} else {
|
||||
b2[bd++] = (unsigned char)o;
|
||||
b2[bd++] = (unsigned char)(o >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (q) {
|
||||
q--;
|
||||
|
||||
if (q > 31) {
|
||||
b2[bd++] = (unsigned char)(224 + (q >> 8));
|
||||
}
|
||||
|
||||
b2[bd++] = (unsigned char)q;
|
||||
q++;
|
||||
|
||||
memcpy(b2 + bd, src + i - q, q);
|
||||
|
||||
bd += q;
|
||||
}
|
||||
|
||||
b2[bd++] = 255;
|
||||
b2 = (unsigned char*)realloc(b2, bd);
|
||||
*size = bd;
|
||||
|
||||
std::vector<uint8_t> compressed_data(b2, b2 + bd);
|
||||
free(b2);
|
||||
return compressed_data;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> HyruleMagicDecompress(uint8_t const* src, int* const size,
|
||||
int const p_big_endian) {
|
||||
unsigned char* b2 = (unsigned char*)malloc(1024);
|
||||
|
||||
int bd = 0, bs = 1024;
|
||||
|
||||
unsigned char a;
|
||||
unsigned char b;
|
||||
unsigned short c, d;
|
||||
|
||||
for (;;) {
|
||||
// retrieve a uchar from the buffer.
|
||||
a = *(src++);
|
||||
|
||||
// end the decompression routine if we encounter 0xff.
|
||||
if (a == 0xff) break;
|
||||
|
||||
// examine the top 3 bits of a.
|
||||
b = (a >> 5);
|
||||
|
||||
if (b == 7) // i.e. 0b 111
|
||||
{
|
||||
// get bits 0b 0001 1100
|
||||
b = ((a >> 2) & 7);
|
||||
|
||||
// get bits 0b 0000 0011, multiply by 256, OR with the next byte.
|
||||
c = ((a & 0x0003) << 8);
|
||||
c |= *(src++);
|
||||
} else
|
||||
// or get bits 0b 0001 1111
|
||||
c = (uint16_t)(a & 31);
|
||||
|
||||
c++;
|
||||
|
||||
if ((bd + c) > (bs - 512)) {
|
||||
// need to increase the buffer size.
|
||||
bs += 1024;
|
||||
b2 = (uint8_t*)realloc(b2, bs);
|
||||
}
|
||||
|
||||
// 7 was handled, here we handle other decompression codes.
|
||||
|
||||
switch (b) {
|
||||
case 0: // 0b 000
|
||||
|
||||
// raw copy
|
||||
|
||||
// copy info from the src buffer to our new buffer,
|
||||
// at offset bd (which we'll be increasing;
|
||||
memcpy(b2 + bd, src, c);
|
||||
|
||||
// increment the src pointer accordingly.
|
||||
src += c;
|
||||
|
||||
bd += c;
|
||||
|
||||
break;
|
||||
|
||||
case 1: // 0b 001
|
||||
|
||||
// rle copy
|
||||
|
||||
// make c duplicates of one byte, inc the src pointer.
|
||||
memset(b2 + bd, *(src++), c);
|
||||
|
||||
// increase the b2 offset.
|
||||
bd += c;
|
||||
|
||||
break;
|
||||
|
||||
case 2: // 0b 010
|
||||
|
||||
// rle 16-bit alternating copy
|
||||
|
||||
d = core::ldle16b(src);
|
||||
|
||||
src += 2;
|
||||
|
||||
while (c > 1) {
|
||||
// copy that 16-bit number c/2 times into the b2 buffer.
|
||||
core::stle16b(b2 + bd, d);
|
||||
|
||||
bd += 2;
|
||||
c -= 2; // hence c/2
|
||||
}
|
||||
|
||||
if (c) // if there's a remainder of c/2, this handles it.
|
||||
b2[bd++] = (char)d;
|
||||
|
||||
break;
|
||||
|
||||
case 3: // 0b 011
|
||||
|
||||
// incrementing copy
|
||||
|
||||
// get the current src byte.
|
||||
a = *(src++);
|
||||
|
||||
while (c--) {
|
||||
// increment that byte and copy to b2 in c iterations.
|
||||
// e.g. a = 4, b2 will have 4,5,6,7,8... written to it.
|
||||
b2[bd++] = a++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default: // 0b 100, 101, 110
|
||||
|
||||
// lz copy
|
||||
|
||||
if (p_big_endian) {
|
||||
d = (*src << 8) + src[1];
|
||||
} else {
|
||||
d = core::ldle16b(src);
|
||||
}
|
||||
|
||||
while (c--) {
|
||||
// copy from a different location in the buffer.
|
||||
b2[bd++] = b2[d++];
|
||||
}
|
||||
|
||||
src += 2;
|
||||
}
|
||||
}
|
||||
|
||||
b2 = (unsigned char*)realloc(b2, bd);
|
||||
|
||||
if (size) (*size) = bd;
|
||||
|
||||
// return the unsigned char* buffer b2, which contains the uncompressed data.
|
||||
std::vector<uint8_t> decompressed_data(b2, b2 + bd);
|
||||
free(b2);
|
||||
return decompressed_data;
|
||||
}
|
||||
|
||||
namespace lc_lz2 {
|
||||
|
||||
void PrintCompressionPiece(const CompressionPiecePointer& piece) {
|
||||
std::cout << "Command: " << std::to_string(piece->command) << "\n";
|
||||
@@ -179,9 +459,6 @@ void CompressionCommandAlternative(const uchar* rom_data,
|
||||
comp_accumulator = 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Compression V2
|
||||
|
||||
void CheckByteRepeatV2(const uchar* data, uint& src_pos, const uint last_pos,
|
||||
CompressionCommand& cmd) {
|
||||
uint i = 0;
|
||||
@@ -380,15 +657,17 @@ absl::StatusOr<CompressionPiecePointer> SplitCompressionPiece(
|
||||
new_piece->argument[0] =
|
||||
(char)(piece->argument[0] + kMaxLengthCompression);
|
||||
break;
|
||||
case kCommandDirectCopy:
|
||||
case kCommandDirectCopy: {
|
||||
std::string empty;
|
||||
piece->argument_length = kMaxLengthCompression;
|
||||
new_piece = std::make_shared<CompressionPiece>(
|
||||
piece->command, length_left, nullptr, length_left);
|
||||
piece->command, length_left, empty, length_left);
|
||||
// MEMCPY
|
||||
for (int i = 0; i < length_left; ++i) {
|
||||
new_piece->argument[i] = piece->argument[i + kMaxLengthCompression];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kCommandRepeatingBytes: {
|
||||
piece->argument_length = kMaxLengthCompression;
|
||||
uint offset = piece->argument[0] + (piece->argument[1] << 8);
|
||||
@@ -526,7 +805,9 @@ absl::StatusOr<std::vector<uint8_t>> CompressV2(const uchar* data,
|
||||
}
|
||||
|
||||
// Worst case should be a copy of the string with extended header
|
||||
auto compressed_chain = std::make_shared<CompressionPiece>(1, 1, "aaa", 2);
|
||||
std::string worst_case = "aaa";
|
||||
auto compressed_chain =
|
||||
std::make_shared<CompressionPiece>(1, 1, worst_case, 2);
|
||||
auto compressed_chain_start = compressed_chain;
|
||||
|
||||
CompressionCommand current_cmd = {/*argument*/ {{}},
|
||||
@@ -590,286 +871,6 @@ absl::StatusOr<std::vector<uint8_t>> CompressV2(const uchar* data,
|
||||
return CreateCompressionString(compressed_chain_start->next, mode);
|
||||
}
|
||||
|
||||
// Hyrule Magic
|
||||
uint8_t* Compress(uint8_t const* const src, int const oldsize, int* const size,
|
||||
int const flag) {
|
||||
unsigned char* b2 =
|
||||
(unsigned char*)malloc(0x1000); // allocate a 2^12 sized buffer
|
||||
|
||||
int i, j, k, l, m = 0, n, o = 0, bd = 0, p, q = 0, r;
|
||||
|
||||
for (i = 0; i < oldsize;) {
|
||||
l = src[i]; // grab a char from the buffer.
|
||||
|
||||
k = 0;
|
||||
|
||||
r = !!q; // r = the same logical value (0 or 1) as q, but not the same
|
||||
// value necesarily.
|
||||
|
||||
for (j = 0; j < i - 1; j++) {
|
||||
if (src[j] == l) {
|
||||
m = oldsize - j;
|
||||
|
||||
for (n = 0; n < m; n++)
|
||||
if (src[n + j] != src[n + i]) break;
|
||||
|
||||
if (n > k) k = n, o = j;
|
||||
}
|
||||
}
|
||||
|
||||
for (n = i + 1; n < oldsize; n++) {
|
||||
if (src[n] != l) {
|
||||
// look for chars identical to the first one.
|
||||
// stop if we can't find one.
|
||||
// n will reach i+k+1 for some k >= 0.
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
n -= i; // offset back by i. i.e. n = k+1 as above.
|
||||
|
||||
if (n > 1 + r)
|
||||
p = 1;
|
||||
else {
|
||||
m = src[i + 1];
|
||||
|
||||
for (n = i + 2; n < oldsize; n++) {
|
||||
if (src[n] != l) break;
|
||||
|
||||
n++;
|
||||
|
||||
if (src[n] != m) break;
|
||||
}
|
||||
|
||||
n -= i;
|
||||
|
||||
if (n > 2 + r)
|
||||
p = 2;
|
||||
else {
|
||||
m = oldsize - i;
|
||||
|
||||
for (n = 1; n < m; n++)
|
||||
if (src[i + n] != l + n) break;
|
||||
|
||||
if (n > 1 + r)
|
||||
p = 3;
|
||||
else
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (k > 3 + r && k > n + (p & 1)) p = 4, n = k;
|
||||
|
||||
if (!p)
|
||||
q++, i++;
|
||||
else {
|
||||
if (q) {
|
||||
q--;
|
||||
|
||||
if (q > 31) {
|
||||
b2[bd++] = (unsigned char)(224 + (q >> 8));
|
||||
}
|
||||
|
||||
b2[bd++] = (unsigned char)q;
|
||||
q++;
|
||||
|
||||
memcpy(b2 + bd, src + i - q, q);
|
||||
|
||||
bd += q;
|
||||
q = 0;
|
||||
}
|
||||
|
||||
i += n;
|
||||
n--;
|
||||
|
||||
if (n > 31) {
|
||||
b2[bd++] = (unsigned char)(224 + (n >> 8) + (p << 2));
|
||||
b2[bd++] = (unsigned char)n;
|
||||
} else
|
||||
b2[bd++] = (unsigned char)((p << 5) + n);
|
||||
|
||||
switch (p) {
|
||||
case 1:
|
||||
case 3:
|
||||
b2[bd++] = (unsigned char)l;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
b2[bd++] = (unsigned char)l;
|
||||
b2[bd++] = (unsigned char)m;
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (flag) {
|
||||
b2[bd++] = (unsigned char)(o >> 8);
|
||||
b2[bd++] = (unsigned char)o;
|
||||
} else {
|
||||
b2[bd++] = (unsigned char)o;
|
||||
b2[bd++] = (unsigned char)(o >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (q) {
|
||||
q--;
|
||||
|
||||
if (q > 31) {
|
||||
b2[bd++] = (unsigned char)(224 + (q >> 8));
|
||||
}
|
||||
|
||||
b2[bd++] = (unsigned char)q;
|
||||
q++;
|
||||
|
||||
memcpy(b2 + bd, src + i - q, q);
|
||||
|
||||
bd += q;
|
||||
}
|
||||
|
||||
b2[bd++] = 255;
|
||||
b2 = (unsigned char*)realloc(b2, bd);
|
||||
*size = bd;
|
||||
|
||||
return b2;
|
||||
}
|
||||
|
||||
uint8_t* Uncompress(uint8_t const* src, int* const size,
|
||||
int const p_big_endian) {
|
||||
unsigned char* b2 = (unsigned char*)malloc(1024);
|
||||
|
||||
int bd = 0, bs = 1024;
|
||||
|
||||
unsigned char a;
|
||||
unsigned char b;
|
||||
unsigned short c, d;
|
||||
|
||||
for (;;) {
|
||||
// retrieve a uchar from the buffer.
|
||||
a = *(src++);
|
||||
|
||||
// end the decompression routine if we encounter 0xff.
|
||||
if (a == 0xff) break;
|
||||
|
||||
// examine the top 3 bits of a.
|
||||
b = (a >> 5);
|
||||
|
||||
if (b == 7) // i.e. 0b 111
|
||||
{
|
||||
// get bits 0b 0001 1100
|
||||
b = ((a >> 2) & 7);
|
||||
|
||||
// get bits 0b 0000 0011, multiply by 256, OR with the next byte.
|
||||
c = ((a & 0x0003) << 8);
|
||||
c |= *(src++);
|
||||
} else
|
||||
// or get bits 0b 0001 1111
|
||||
c = (uint16_t)(a & 31);
|
||||
|
||||
c++;
|
||||
|
||||
if ((bd + c) > (bs - 512)) {
|
||||
// need to increase the buffer size.
|
||||
bs += 1024;
|
||||
b2 = (uint8_t*)realloc(b2, bs);
|
||||
}
|
||||
|
||||
// 7 was handled, here we handle other decompression codes.
|
||||
|
||||
switch (b) {
|
||||
case 0: // 0b 000
|
||||
|
||||
// raw copy
|
||||
|
||||
// copy info from the src buffer to our new buffer,
|
||||
// at offset bd (which we'll be increasing;
|
||||
memcpy(b2 + bd, src, c);
|
||||
|
||||
// increment the src pointer accordingly.
|
||||
src += c;
|
||||
|
||||
bd += c;
|
||||
|
||||
break;
|
||||
|
||||
case 1: // 0b 001
|
||||
|
||||
// rle copy
|
||||
|
||||
// make c duplicates of one byte, inc the src pointer.
|
||||
memset(b2 + bd, *(src++), c);
|
||||
|
||||
// increase the b2 offset.
|
||||
bd += c;
|
||||
|
||||
break;
|
||||
|
||||
case 2: // 0b 010
|
||||
|
||||
// rle 16-bit alternating copy
|
||||
|
||||
d = core::ldle16b(src);
|
||||
|
||||
src += 2;
|
||||
|
||||
while (c > 1) {
|
||||
// copy that 16-bit number c/2 times into the b2 buffer.
|
||||
core::stle16b(b2 + bd, d);
|
||||
|
||||
bd += 2;
|
||||
c -= 2; // hence c/2
|
||||
}
|
||||
|
||||
if (c) // if there's a remainder of c/2, this handles it.
|
||||
b2[bd++] = (char)d;
|
||||
|
||||
break;
|
||||
|
||||
case 3: // 0b 011
|
||||
|
||||
// incrementing copy
|
||||
|
||||
// get the current src byte.
|
||||
a = *(src++);
|
||||
|
||||
while (c--) {
|
||||
// increment that byte and copy to b2 in c iterations.
|
||||
// e.g. a = 4, b2 will have 4,5,6,7,8... written to it.
|
||||
b2[bd++] = a++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default: // 0b 100, 101, 110
|
||||
|
||||
// lz copy
|
||||
|
||||
if (p_big_endian) {
|
||||
d = (*src << 8) + src[1];
|
||||
} else {
|
||||
d = core::ldle16b(src);
|
||||
}
|
||||
|
||||
while (c--) {
|
||||
// copy from a different location in the buffer.
|
||||
b2[bd++] = b2[d++];
|
||||
}
|
||||
|
||||
src += 2;
|
||||
}
|
||||
}
|
||||
|
||||
b2 = (unsigned char*)realloc(b2, bd);
|
||||
|
||||
if (size) (*size) = bd;
|
||||
|
||||
// return the unsigned char* buffer b2, which contains the uncompressed data.
|
||||
return b2;
|
||||
}
|
||||
|
||||
absl::StatusOr<std::vector<uint8_t>> CompressGraphics(const uchar* data,
|
||||
const int pos,
|
||||
const int length) {
|
||||
@@ -887,9 +888,6 @@ absl::StatusOr<std::vector<uint8_t>> CompressOverworld(
|
||||
return CompressV3(data, pos, length, kNintendoMode1);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Compression V3
|
||||
|
||||
void CheckByteRepeatV3(CompressionContext& context) {
|
||||
uint pos = context.src_pos;
|
||||
|
||||
@@ -1209,15 +1207,17 @@ absl::StatusOr<CompressionPiece> SplitCompressionPieceV3(
|
||||
piece.argument_length);
|
||||
new_piece.argument[0] = (char)(piece.argument[0] + kMaxLengthCompression);
|
||||
break;
|
||||
case kCommandDirectCopy:
|
||||
case kCommandDirectCopy: {
|
||||
piece.argument_length = kMaxLengthCompression;
|
||||
new_piece =
|
||||
CompressionPiece(piece.command, length_left, nullptr, length_left);
|
||||
std::string empty_string = "";
|
||||
new_piece = CompressionPiece(piece.command, length_left, empty_string,
|
||||
length_left);
|
||||
// MEMCPY
|
||||
for (int i = 0; i < length_left; ++i) {
|
||||
new_piece.argument[i] = piece.argument[i + kMaxLengthCompression];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kCommandRepeatingBytes: {
|
||||
piece.argument_length = kMaxLengthCompression;
|
||||
uint offset = piece.argument[0] + (piece.argument[1] << 8);
|
||||
@@ -1340,8 +1340,6 @@ absl::StatusOr<std::vector<uint8_t>> CompressV3(
|
||||
context.compressed_data.end());
|
||||
}
|
||||
|
||||
// Decompression
|
||||
|
||||
std::string SetBuffer(const uchar* data, int src_pos, int comp_accumulator) {
|
||||
std::string buffer;
|
||||
for (int i = 0; i < comp_accumulator; ++i) {
|
||||
@@ -1473,5 +1471,4 @@ absl::StatusOr<std::vector<uint8_t>> DecompressOverworld(
|
||||
|
||||
} // namespace lc_lz2
|
||||
} // namespace gfx
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
} // namespace yaze
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
@@ -11,11 +12,17 @@
|
||||
#define BUILD_HEADER(command, length) (command << 5) + (length - 1)
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace gfx {
|
||||
|
||||
std::vector<uint8_t> HyruleMagicCompress(uint8_t const* const src,
|
||||
int const oldsize, int* const size,
|
||||
int const flag);
|
||||
|
||||
std::vector<uint8_t> HyruleMagicDecompress(uint8_t const* src, int* const size,
|
||||
int const p_big_endian);
|
||||
|
||||
/**
|
||||
* @namespace yaze::app::gfx::lc_lz2
|
||||
* @namespace yaze::gfx::lc_lz2
|
||||
* @brief Contains the LC_LZ2 compression algorithm.
|
||||
*/
|
||||
namespace lc_lz2 {
|
||||
@@ -75,7 +82,7 @@ struct CompressionPiece {
|
||||
std::string argument;
|
||||
std::shared_ptr<CompressionPiece> next = nullptr;
|
||||
CompressionPiece() = default;
|
||||
CompressionPiece(int cmd, int len, std::string args, int arg_len)
|
||||
CompressionPiece(int cmd, int len, std::string& args, int arg_len)
|
||||
: command(cmd), length(len), argument_length(arg_len), argument(args) {}
|
||||
};
|
||||
using CompressionPiece = struct CompressionPiece;
|
||||
@@ -139,31 +146,33 @@ void CompressionCommandAlternativeV2(const uchar* data,
|
||||
|
||||
/**
|
||||
* @brief Compresses a buffer of data using the LC_LZ2 algorithm.
|
||||
* \deprecated Use Compress and Uncompress instead.
|
||||
* \deprecated Use HyruleMagicDecompress instead.
|
||||
*/
|
||||
absl::StatusOr<std::vector<uint8_t>> CompressV2(const uchar* data, const int start,
|
||||
const int length, int mode = 1,
|
||||
bool check = false);
|
||||
absl::StatusOr<std::vector<uint8_t>> CompressV2(const uchar* data,
|
||||
const int start,
|
||||
const int length, int mode = 1,
|
||||
bool check = false);
|
||||
|
||||
absl::StatusOr<std::vector<uint8_t>> CompressGraphics(const uchar* data, const int pos,
|
||||
const int length);
|
||||
absl::StatusOr<std::vector<uint8_t>> CompressOverworld(const uchar* data, const int pos,
|
||||
const int length);
|
||||
absl::StatusOr<std::vector<uint8_t>> CompressOverworld(const std::vector<uint8_t> data,
|
||||
const int pos, const int length);
|
||||
absl::StatusOr<std::vector<uint8_t>> CompressGraphics(const uchar* data,
|
||||
const int pos,
|
||||
const int length);
|
||||
absl::StatusOr<std::vector<uint8_t>> CompressOverworld(const uchar* data,
|
||||
const int pos,
|
||||
const int length);
|
||||
absl::StatusOr<std::vector<uint8_t>> CompressOverworld(
|
||||
const std::vector<uint8_t> data, const int pos, const int length);
|
||||
|
||||
absl::StatusOr<CompressionPiecePointer> SplitCompressionPiece(
|
||||
CompressionPiecePointer& piece, int mode);
|
||||
|
||||
std::vector<uint8_t> CreateCompressionString(CompressionPiecePointer& start, int mode);
|
||||
std::vector<uint8_t> CreateCompressionString(CompressionPiecePointer& start,
|
||||
int mode);
|
||||
|
||||
absl::Status ValidateCompressionResult(CompressionPiecePointer& chain_head,
|
||||
int mode, int start, int src_data_pos);
|
||||
|
||||
CompressionPiecePointer MergeCopy(CompressionPiecePointer& start);
|
||||
|
||||
// Compression V3
|
||||
|
||||
struct CompressionContext {
|
||||
std::vector<uint8_t> data;
|
||||
std::vector<uint8_t> compressed_data;
|
||||
@@ -210,42 +219,35 @@ void FinalizeCompression(CompressionContext& context);
|
||||
|
||||
/**
|
||||
* @brief Compresses a buffer of data using the LC_LZ2 algorithm.
|
||||
* \deprecated Use Compress and Uncompress instead.
|
||||
* \deprecated Use HyruleMagicCompress
|
||||
*/
|
||||
absl::StatusOr<std::vector<uint8_t>> CompressV3(const std::vector<uint8_t>& data,
|
||||
const int start, const int length,
|
||||
int mode = 1, bool check = false);
|
||||
|
||||
// Hyrule Magic
|
||||
uint8_t* Compress(uint8_t const* const src, int const oldsize, int* const size,
|
||||
int const flag);
|
||||
|
||||
uint8_t* Uncompress(uint8_t const* src, int* const size,
|
||||
int const p_big_endian);
|
||||
|
||||
// Decompression
|
||||
absl::StatusOr<std::vector<uint8_t>> CompressV3(
|
||||
const std::vector<uint8_t>& data, const int start, const int length,
|
||||
int mode = 1, bool check = false);
|
||||
|
||||
std::string SetBuffer(const std::vector<uint8_t>& data, int src_pos,
|
||||
int comp_accumulator);
|
||||
std::string SetBuffer(const uchar* data, int src_pos, int comp_accumulator);
|
||||
void memfill(const uchar* data, std::vector<uint8_t>& buffer, int buffer_pos, int offset,
|
||||
int length);
|
||||
void memfill(const uchar* data, std::vector<uint8_t>& buffer, int buffer_pos,
|
||||
int offset, int length);
|
||||
|
||||
/**
|
||||
* @brief Decompresses a buffer of data using the LC_LZ2 algorithm.
|
||||
* \deprecated Use Compress and Uncompress instead.
|
||||
* @note Works well for graphics but not overworld data. Prefer Hyrule Magic
|
||||
* routines for overworld data.
|
||||
*/
|
||||
absl::StatusOr<std::vector<uint8_t>> DecompressV2(const uchar* data, int offset,
|
||||
int size = 0x800, int mode = 1);
|
||||
absl::StatusOr<std::vector<uint8_t>> DecompressGraphics(const uchar* data, int pos, int size);
|
||||
absl::StatusOr<std::vector<uint8_t>> DecompressOverworld(const uchar* data, int pos, int size);
|
||||
absl::StatusOr<std::vector<uint8_t>> DecompressOverworld(const std::vector<uint8_t> data,
|
||||
int pos, int size);
|
||||
int size = 0x800,
|
||||
int mode = 1);
|
||||
absl::StatusOr<std::vector<uint8_t>> DecompressGraphics(const uchar* data,
|
||||
int pos, int size);
|
||||
absl::StatusOr<std::vector<uint8_t>> DecompressOverworld(const uchar* data,
|
||||
int pos, int size);
|
||||
absl::StatusOr<std::vector<uint8_t>> DecompressOverworld(
|
||||
const std::vector<uint8_t> data, int pos, int size);
|
||||
|
||||
} // namespace lc_lz2
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_GFX_COMPRESSION_H
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user