backend-infra-engineer: Release 0.2.2 snapshot

This commit is contained in:
scawful
2024-12-31 21:00:27 -05:00
parent 18b7fb9abf
commit 8ce29e1436
209 changed files with 7446 additions and 3633 deletions

View File

@@ -105,6 +105,7 @@ if (YAZE_BUILD_LIB)
${CMAKE_SOURCE_DIR}/src/
${PNG_INCLUDE_DIRS}
${SDL2_INCLUDE_DIR}
${PROJECT_BINARY_DIR}
)
target_link_libraries(

View File

@@ -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()

View File

@@ -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 &params) {
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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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];

View File

@@ -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

View File

@@ -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

View File

@@ -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];

View File

@@ -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

View File

@@ -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:@"/"];

View File

@@ -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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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_

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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", &current_room_id_);
gui::InputHex("Palette ID", &current_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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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", &current_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", &current_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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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", &notify_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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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_

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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_

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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_

View File

@@ -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

View File

@@ -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_

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -24,6 +24,7 @@ target_include_directories(
${CMAKE_SOURCE_DIR}/src/
${PNG_INCLUDE_DIRS}
${SDL2_INCLUDE_DIR}
${PROJECT_BINARY_DIR}
)
target_link_libraries(

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

Some files were not shown because too many files have changed in this diff Show More