Update PaletteEditor, remove Delta experiment
This commit is contained in:
@@ -129,57 +129,4 @@ set_target_properties(yaze
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
|
||||
LINK_FLAGS "${CMAKE_CURRENT_SOURCE_DIR}/yaze.res"
|
||||
)
|
||||
endif()
|
||||
|
||||
# add_subdirectory(app/delta)
|
||||
|
||||
# add_executable(
|
||||
# yaze_delta
|
||||
# app/delta/delta.cc
|
||||
# app/delta/viewer.cc
|
||||
# app/delta/service.cc
|
||||
# app/delta/client.cc
|
||||
# app/rom.cc
|
||||
# ${YAZE_APP_ASM_SRC}
|
||||
# ${YAZE_APP_CORE_SRC}
|
||||
# ${YAZE_APP_EDITOR_SRC}
|
||||
# ${YAZE_APP_GFX_SRC}
|
||||
# ${YAZE_APP_ZELDA3_SRC}
|
||||
# ${YAZE_GUI_SRC}
|
||||
# ${IMGUI_SRC}
|
||||
# ${ASAR_STATIC_SRC}
|
||||
# )
|
||||
|
||||
# target_include_directories(
|
||||
# yaze_delta PUBLIC
|
||||
# lib/
|
||||
# app/
|
||||
# lib/asar/src/
|
||||
# ${ASAR_INCLUDE_DIR}
|
||||
# ${CMAKE_SOURCE_DIR}/src/
|
||||
# ${PNG_INCLUDE_DIRS}
|
||||
# ${SDL2_INCLUDE_DIR}
|
||||
# ${GLEW_INCLUDE_DIRS}
|
||||
# )
|
||||
|
||||
# target_link_libraries(
|
||||
# yaze_delta PUBLIC
|
||||
# ${ABSL_TARGETS}
|
||||
# ${SDL_TARGETS}
|
||||
# ${PNG_LIBRARIES}
|
||||
# ${GLEW_LIBRARIES}
|
||||
# ${OPENGL_LIBRARIES}
|
||||
# ${CMAKE_DL_LIBS}
|
||||
# delta-service
|
||||
# asar-static
|
||||
# ImGui
|
||||
# )
|
||||
# target_compile_definitions(yaze_delta PRIVATE "linux")
|
||||
# target_compile_definitions(yaze_delta PRIVATE "stricmp=strcasecmp")
|
||||
|
||||
# set (source "${CMAKE_SOURCE_DIR}/assets")
|
||||
# set (destination "${CMAKE_CURRENT_BINARY_DIR}/assets")
|
||||
# add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||
# COMMAND ${CMAKE_COMMAND} -E create_symlink ${source} ${destination}
|
||||
# DEPENDS ${destination}
|
||||
# COMMENT "symbolic link resources folder from ${source} => ${destination}")
|
||||
endif()
|
||||
@@ -65,6 +65,10 @@
|
||||
|
||||
#define APPEND_NUMBER_INNER(expression, number) expression##number
|
||||
|
||||
#define TEXT_WITH_SEPARATOR(text) \
|
||||
ImGui::Text(text); \
|
||||
ImGui::Separator();
|
||||
|
||||
using ushort = unsigned short;
|
||||
using uint = unsigned int;
|
||||
using uchar = unsigned char;
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
|
||||
add_library(delta-service delta.proto)
|
||||
target_link_libraries(delta-service
|
||||
PUBLIC
|
||||
protobuf::libprotobuf
|
||||
gRPC::grpc
|
||||
gRPC::grpc++
|
||||
)
|
||||
|
||||
target_include_directories(delta-service
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${PROTOBUF_INCLUDE_PATH}
|
||||
)
|
||||
|
||||
get_target_property(grpc_cpp_plugin_location gRPC::grpc_cpp_plugin LOCATION)
|
||||
|
||||
# compile the message types
|
||||
protobuf_generate(TARGET delta-service LANGUAGE cpp)
|
||||
|
||||
# compile the GRPC services
|
||||
protobuf_generate(
|
||||
TARGET
|
||||
delta-service
|
||||
LANGUAGE
|
||||
grpc
|
||||
GENERATE_EXTENSIONS
|
||||
.grpc.pb.h
|
||||
.grpc.pb.cc
|
||||
PLUGIN
|
||||
"protoc-gen-grpc=${grpc_cpp_plugin_location}"
|
||||
)
|
||||
@@ -1,54 +0,0 @@
|
||||
#include "client.h"
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpcpp/ext/proto_server_reflection_plugin.h>
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <grpcpp/health_check_service_interface.h>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "src/app/delta/delta.grpc.pb.h"
|
||||
#include "src/app/delta/delta.pb.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace delta {
|
||||
|
||||
using grpc::Channel;
|
||||
using grpc::ClientAsyncResponseReader;
|
||||
using grpc::ClientContext;
|
||||
using grpc::CompletionQueue;
|
||||
using grpc::Server;
|
||||
using grpc::ServerBuilder;
|
||||
using grpc::Status;
|
||||
|
||||
void Client::CreateChannel() {
|
||||
auto channel = grpc::CreateChannel("localhost:50051",
|
||||
grpc::InsecureChannelCredentials());
|
||||
stub_ = ::YazeDelta::NewStub(channel);
|
||||
}
|
||||
|
||||
absl::Status Client::InitRepo(std::string author_name,
|
||||
std::string project_name) {
|
||||
Repository new_repo;
|
||||
new_repo.set_author_name(author_name);
|
||||
new_repo.set_project_name(project_name);
|
||||
new_repo.mutable_tree()->Add();
|
||||
|
||||
InitRequest request;
|
||||
request.set_allocated_repo(&new_repo);
|
||||
|
||||
InitResponse response;
|
||||
Status status = stub_->Init(&rpc_context, request, &response);
|
||||
|
||||
if (!status.ok()) {
|
||||
std::cerr << status.error_code() << ": " << status.error_message()
|
||||
<< std::endl;
|
||||
return absl::InternalError(status.error_message());
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace delta
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
@@ -1,44 +0,0 @@
|
||||
#ifndef YAZE_APP_DELTA_CLIENT_H
|
||||
#define YAZE_APP_DELTA_CLIENT_H
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpcpp/ext/proto_server_reflection_plugin.h>
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <grpcpp/health_check_service_interface.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "src/app/delta/delta.grpc.pb.h"
|
||||
#include "src/app/delta/delta.pb.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace delta {
|
||||
|
||||
using grpc::Channel;
|
||||
using grpc::ClientAsyncResponseReader;
|
||||
using grpc::ClientContext;
|
||||
using grpc::CompletionQueue;
|
||||
using grpc::Server;
|
||||
using grpc::ServerBuilder;
|
||||
using grpc::Status;
|
||||
|
||||
class Client {
|
||||
public:
|
||||
Client() = default;
|
||||
void CreateChannel();
|
||||
absl::Status InitRepo(std::string author_name, std::string project_name);
|
||||
|
||||
private:
|
||||
ClientContext rpc_context;
|
||||
std::vector<Repository> repos_;
|
||||
std::unique_ptr<YazeDelta::Stub> stub_;
|
||||
};
|
||||
|
||||
} // namespace delta
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
@@ -1,32 +0,0 @@
|
||||
#if defined(_WIN32)
|
||||
#define main SDL_main
|
||||
#endif
|
||||
|
||||
#include "absl/debugging/failure_signal_handler.h"
|
||||
#include "absl/debugging/symbolize.h"
|
||||
#include "app/core/controller.h"
|
||||
#include "app/delta/viewer.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
absl::InitializeSymbolizer(argv[0]);
|
||||
|
||||
absl::FailureSignalHandlerOptions options;
|
||||
absl::InstallFailureSignalHandler(options);
|
||||
|
||||
yaze::app::core::Controller controller;
|
||||
yaze::app::delta::Viewer viewer;
|
||||
|
||||
auto entry_status = controller.onEntry();
|
||||
if (!entry_status.ok()) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
while (controller.isActive()) {
|
||||
controller.onInput();
|
||||
viewer.Update();
|
||||
controller.doRender();
|
||||
}
|
||||
controller.onExit();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
syntax = "proto3";
|
||||
option cc_enable_arenas = true;
|
||||
|
||||
service YazeDelta {
|
||||
rpc Init(InitRequest) returns (InitResponse) {}
|
||||
|
||||
rpc Clone(CloneRequest) returns (CloneResponse) {}
|
||||
|
||||
rpc Push(PushRequest) returns (PushResponse) {}
|
||||
rpc Pull(PullRequest) returns (PullResponse) {}
|
||||
|
||||
rpc Sync(stream SyncRequest) returns (stream SyncResponse) {}
|
||||
|
||||
rpc CreateBranch(CreateBranchRequest) returns (CreateBranchResponse) {}
|
||||
rpc DeleteBranch(DeleteBranchRequest) returns (DeleteBranchResponse) {}
|
||||
|
||||
rpc Merge(MergeRequest) returns (MergeResponse) {}
|
||||
rpc UndoMerge(UndoMergeRequest) returns (UndoMergeResponse) {}
|
||||
}
|
||||
|
||||
enum ChangeType {
|
||||
OVERWORLD_MAP = 0;
|
||||
DUNGEON_MAP = 1;
|
||||
MONOLOGUE = 2;
|
||||
PALETTE = 3;
|
||||
OBJECT = 4;
|
||||
ASSEMBLY = 5;
|
||||
MISC = 6;
|
||||
}
|
||||
|
||||
message Delta {
|
||||
int64 offset = 1;
|
||||
int64 length = 2;
|
||||
bytes data = 3;
|
||||
ChangeType type = 4;
|
||||
}
|
||||
|
||||
message Commit {
|
||||
int64 commit_id = 1;
|
||||
int64 parent_commit_id = 2;
|
||||
string author_name = 3;
|
||||
string message_header = 4;
|
||||
optional string message_body = 5;
|
||||
repeated Delta delta = 6;
|
||||
int64 signature = 7;
|
||||
}
|
||||
|
||||
message Branch {
|
||||
string branch_name = 1;
|
||||
optional string parent_name = 2;
|
||||
repeated Commit commits = 3;
|
||||
}
|
||||
|
||||
message Repository {
|
||||
string project_name = 1;
|
||||
string author_name = 2;
|
||||
int64 signature = 3;
|
||||
optional bool locked = 4;
|
||||
optional string password = 5;
|
||||
repeated Branch tree = 6;
|
||||
}
|
||||
|
||||
message InitRequest {
|
||||
Repository repo = 1;
|
||||
}
|
||||
|
||||
message InitResponse {
|
||||
int32 response = 1;
|
||||
}
|
||||
|
||||
message CloneRequest {}
|
||||
|
||||
message CloneResponse {}
|
||||
|
||||
message PushRequest {
|
||||
string author_name = 1;
|
||||
string repository_name= 2;
|
||||
string branch_name = 3;
|
||||
repeated Commit commits = 4;
|
||||
}
|
||||
message PushResponse {}
|
||||
|
||||
message PullRequest {
|
||||
string repository_name = 1;
|
||||
string branch_name = 2;
|
||||
repeated Commit commits = 3;
|
||||
}
|
||||
|
||||
message PullResponse {}
|
||||
|
||||
message SyncRequest {}
|
||||
|
||||
message SyncResponse {}
|
||||
|
||||
message CreateBranchRequest {}
|
||||
message CreateBranchResponse {}
|
||||
|
||||
message DeleteBranchRequest {}
|
||||
message DeleteBranchResponse {}
|
||||
|
||||
message MergeRequest {}
|
||||
message MergeResponse {}
|
||||
|
||||
message UndoMergeRequest {}
|
||||
message UndoMergeResponse {}
|
||||
@@ -1,87 +0,0 @@
|
||||
#include "service.h"
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpcpp/ext/proto_server_reflection_plugin.h>
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <grpcpp/health_check_service_interface.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "src/app/delta/delta.grpc.pb.h"
|
||||
#include "src/app/delta/delta.pb.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace delta {
|
||||
|
||||
using grpc::Channel;
|
||||
using grpc::ClientAsyncResponseReader;
|
||||
using grpc::ClientContext;
|
||||
using grpc::CompletionQueue;
|
||||
using grpc::Server;
|
||||
using grpc::ServerBuilder;
|
||||
using grpc::Status;
|
||||
|
||||
namespace {
|
||||
auto FindRepository(std::vector<Repository>& repos, const std::string& name) {
|
||||
for (auto& repo : repos) {
|
||||
if (repo.project_name() == name) {
|
||||
return repo.mutable_tree();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto FindBranch(google::protobuf::RepeatedPtrField<Branch>* repo,
|
||||
const std::string& branch_name) {
|
||||
for (auto it = repo->begin(); it != repo->end(); ++it) {
|
||||
if (it->branch_name() == branch_name) {
|
||||
return it->mutable_commits();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Status DeltaService::Init(grpc::ServerContext* context,
|
||||
const InitRequest* request, InitResponse* reply) {
|
||||
std::filesystem::create_directories("./.yaze");
|
||||
repos_.push_back(request->repo());
|
||||
// std::ofstream commit_stream("./.yaze/commits");
|
||||
// for (const auto& repo : repos_) {
|
||||
// for (const auto& branch : repo.tree()) {
|
||||
// for (const auto& commit : branch.commits()) {
|
||||
// commit_stream << commit.DebugString();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
Status DeltaService::Push(grpc::ServerContext* context,
|
||||
const PushRequest* request, PushResponse* reply) {
|
||||
const auto& repository_name = request->repository_name();
|
||||
const auto& branch_name = request->branch_name();
|
||||
auto repo = FindRepository(repos_, repository_name);
|
||||
auto mutable_commits = FindBranch(repo, branch_name);
|
||||
auto size = request->commits().size();
|
||||
for (int i = 1; i < size; ++i) {
|
||||
*mutable_commits->Add() = request->commits().at(i);
|
||||
}
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
Status DeltaService::Pull(grpc::ServerContext* context,
|
||||
const PullRequest* request, PullResponse* reply) {
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
Status DeltaService::Clone(grpc::ServerContext* context,
|
||||
const CloneRequest* request, CloneResponse* reply) {
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
} // namespace delta
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
@@ -1,48 +0,0 @@
|
||||
#ifndef YAZE_APP_DELTA_SERVICE_H
|
||||
#define YAZE_APP_DELTA_SERVICE_H
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
#include <grpc/support/log.h>
|
||||
#include <grpcpp/ext/proto_server_reflection_plugin.h>
|
||||
#include <grpcpp/grpcpp.h>
|
||||
#include <grpcpp/health_check_service_interface.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "src/app/delta/delta.grpc.pb.h"
|
||||
#include "src/app/delta/delta.pb.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace delta {
|
||||
|
||||
using grpc::Status;
|
||||
|
||||
class DeltaService final : public ::YazeDelta::Service {
|
||||
public:
|
||||
Status Init(grpc::ServerContext* context, const InitRequest* request,
|
||||
InitResponse* reply) override;
|
||||
|
||||
Status Push(grpc::ServerContext* context, const PushRequest* request,
|
||||
PushResponse* reply) override;
|
||||
|
||||
Status Pull(grpc::ServerContext* context, const PullRequest* request,
|
||||
PullResponse* reply) override;
|
||||
|
||||
Status Clone(grpc::ServerContext* context, const CloneRequest* request,
|
||||
CloneResponse* reply) override;
|
||||
|
||||
auto Repos() const { return repos_; }
|
||||
|
||||
private:
|
||||
std::vector<Repository> repos_;
|
||||
};
|
||||
|
||||
} // namespace delta
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
@@ -1,229 +0,0 @@
|
||||
#include "viewer.h"
|
||||
|
||||
#include <ImGuiColorTextEdit/TextEditor.h>
|
||||
#include <ImGuiFileDialog/ImGuiFileDialog.h>
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui/misc/cpp/imgui_stdlib.h>
|
||||
#include <imgui_memory_editor.h>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "app/core/constants.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/rom.h"
|
||||
#include "gui/canvas.h"
|
||||
#include "gui/icons.h"
|
||||
#include "gui/input.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace delta {
|
||||
namespace {
|
||||
|
||||
constexpr ImGuiWindowFlags kMainEditorFlags =
|
||||
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse |
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar |
|
||||
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoTitleBar;
|
||||
|
||||
void NewMasterFrame() {
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui::NewFrame();
|
||||
ImGui::SetNextWindowPos(ImVec2(0, 0));
|
||||
ImVec2 dimensions(io.DisplaySize.x, io.DisplaySize.y);
|
||||
ImGui::SetNextWindowSize(dimensions, ImGuiCond_Always);
|
||||
|
||||
if (!ImGui::Begin("##YazeMain", nullptr, kMainEditorFlags)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Viewer::Update() {
|
||||
NewMasterFrame();
|
||||
DrawYazeMenu();
|
||||
DrawFileDialog();
|
||||
|
||||
ImGui::Text(ICON_MD_CHANGE_HISTORY);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", rom_.GetTitle());
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Button(ICON_MD_SYNC);
|
||||
ImGui::SameLine();
|
||||
ImGui::Button(ICON_MD_ARROW_UPWARD);
|
||||
ImGui::SameLine();
|
||||
ImGui::Button(ICON_MD_ARROW_DOWNWARD);
|
||||
ImGui::SameLine();
|
||||
ImGui::Button(ICON_MD_MERGE);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Button(ICON_MD_MANAGE_HISTORY);
|
||||
ImGui::SameLine();
|
||||
ImGui::Button(ICON_MD_LAN);
|
||||
ImGui::SameLine();
|
||||
ImGui::Button(ICON_MD_COMMIT);
|
||||
ImGui::SameLine();
|
||||
ImGui::Button(ICON_MD_DIFFERENCE);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::SetNextItemWidth(75.f);
|
||||
ImGui::Button(ICON_MD_SEND);
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("Server Address", &client_address_);
|
||||
|
||||
ImGui::SetNextItemWidth(75.f);
|
||||
ImGui::Button(ICON_MD_DOWNLOAD);
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("Repository Source", &client_address_);
|
||||
|
||||
ImGui::Separator();
|
||||
DrawBranchTree();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void Viewer::DrawFileDialog() {
|
||||
if (ImGuiFileDialog::Instance()->Display("ChooseFileDlgKey")) {
|
||||
if (ImGuiFileDialog::Instance()->IsOk()) {
|
||||
std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName();
|
||||
rom_.LoadFromFile(filePathName);
|
||||
}
|
||||
ImGuiFileDialog::Instance()->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void Viewer::DrawYazeMenu() {
|
||||
MENU_BAR()
|
||||
DrawFileMenu();
|
||||
DrawViewMenu();
|
||||
END_MENU_BAR()
|
||||
}
|
||||
|
||||
void Viewer::DrawFileMenu() const {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
if (ImGui::MenuItem("Open", "Ctrl+O")) {
|
||||
ImGuiFileDialog::Instance()->OpenDialog("ChooseFileDlgKey", "Open ROM",
|
||||
".sfc,.smc", ".");
|
||||
}
|
||||
|
||||
MENU_ITEM2("Save", "Ctrl+S") {}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void Viewer::DrawViewMenu() {
|
||||
static bool show_imgui_metrics = false;
|
||||
static bool show_imgui_style_editor = false;
|
||||
static bool show_memory_editor = false;
|
||||
static bool show_imgui_demo = false;
|
||||
|
||||
if (show_imgui_metrics) {
|
||||
ImGui::ShowMetricsWindow(&show_imgui_metrics);
|
||||
}
|
||||
|
||||
if (show_memory_editor) {
|
||||
static MemoryEditor mem_edit;
|
||||
mem_edit.DrawWindow("Memory Editor", (void*)&rom_, rom_.size());
|
||||
}
|
||||
|
||||
if (show_imgui_demo) {
|
||||
ImGui::ShowDemoWindow();
|
||||
}
|
||||
|
||||
if (show_imgui_style_editor) {
|
||||
ImGui::Begin("Style Editor (ImGui)", &show_imgui_style_editor);
|
||||
ImGui::ShowStyleEditor();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("View")) {
|
||||
ImGui::MenuItem("HEX Editor", nullptr, &show_memory_editor);
|
||||
ImGui::MenuItem("ImGui Demo", nullptr, &show_imgui_demo);
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginMenu("GUI Tools")) {
|
||||
ImGui::MenuItem("Metrics (ImGui)", nullptr, &show_imgui_metrics);
|
||||
ImGui::MenuItem("Style Editor (ImGui)", nullptr,
|
||||
&show_imgui_style_editor);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void Viewer::DrawBranchTree() {
|
||||
static ImGuiTableFlags flags =
|
||||
ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH |
|
||||
ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg |
|
||||
ImGuiTableFlags_NoBordersInBody;
|
||||
|
||||
if (ImGui::BeginTable("3ways", 3, flags)) {
|
||||
// The first column will use the default _WidthStretch when ScrollX is Off
|
||||
// and _WidthFixed when ScrollX is On
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide);
|
||||
ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthFixed,
|
||||
10 * 12.0f);
|
||||
ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed,
|
||||
10 * 18.0f);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
// Simple storage to output a dummy file-system.
|
||||
struct MyTreeNode {
|
||||
const char* Name;
|
||||
const char* Type;
|
||||
int Size;
|
||||
int ChildIdx;
|
||||
int ChildCount;
|
||||
static void DisplayNode(const MyTreeNode* node,
|
||||
const MyTreeNode* all_nodes) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
const bool is_folder = (node->ChildCount > 0);
|
||||
if (is_folder) {
|
||||
bool open =
|
||||
ImGui::TreeNodeEx(node->Name, ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextDisabled("--");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(node->Type);
|
||||
if (open) {
|
||||
for (int child_n = 0; child_n < node->ChildCount; child_n++)
|
||||
DisplayNode(&all_nodes[node->ChildIdx + child_n], all_nodes);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
} else {
|
||||
ImGui::TreeNodeEx(
|
||||
node->Name, ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet |
|
||||
ImGuiTreeNodeFlags_NoTreePushOnOpen |
|
||||
ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d", node->Size);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(node->Type);
|
||||
}
|
||||
}
|
||||
};
|
||||
static const MyTreeNode nodes[] = {
|
||||
{"lttp-redux", "Repository", -1, 1, 3},
|
||||
{"main", "Branch", -1, 4, 2},
|
||||
{"hyrule-castle", "Branch", -1, 4, 2},
|
||||
{"lost-woods", "Branch", -1, 6, 3},
|
||||
{"Added some bushes", "Commit", 1024, -1, -1},
|
||||
{"Constructed a new house", "Commit", 123000, -1, -1},
|
||||
{"File1_b.wav", "Commit", 456000, -1, -1},
|
||||
{"Image001.png", "Commit", 203128, -1, -1},
|
||||
{"Copy of Image001.png", "Commit", 203256, -1, -1},
|
||||
{"Copy of Image001 (Final2).png", "Commit", 203512, -1, -1},
|
||||
};
|
||||
|
||||
MyTreeNode::DisplayNode(&nodes[0], nodes);
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
} // namespace delta
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
@@ -1,45 +0,0 @@
|
||||
#ifndef YAZE_APP_DELTA_VIEWER_H
|
||||
#define YAZE_APP_DELTA_VIEWER_H
|
||||
|
||||
#include <ImGuiColorTextEdit/TextEditor.h>
|
||||
#include <ImGuiFileDialog/ImGuiFileDialog.h>
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui/misc/cpp/imgui_stdlib.h>
|
||||
#include <imgui_memory_editor.h>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "app/core/constants.h"
|
||||
#include "app/delta/client.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/rom.h"
|
||||
#include "gui/canvas.h"
|
||||
#include "gui/icons.h"
|
||||
#include "gui/input.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace delta {
|
||||
class Viewer {
|
||||
public:
|
||||
void Update();
|
||||
|
||||
private:
|
||||
void DrawFileDialog();
|
||||
|
||||
void DrawYazeMenu();
|
||||
void DrawFileMenu() const;
|
||||
void DrawViewMenu();
|
||||
|
||||
void DrawBranchTree();
|
||||
|
||||
std::string client_address_;
|
||||
|
||||
ROM rom_;
|
||||
Client client_;
|
||||
};
|
||||
} // namespace delta
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
@@ -7,34 +7,113 @@
|
||||
#include "gui/canvas.h"
|
||||
#include "gui/icons.h"
|
||||
|
||||
static inline float ImSaturate(float f) {
|
||||
return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f;
|
||||
}
|
||||
|
||||
#define IM_F32_TO_INT8_SAT(_VAL) \
|
||||
((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
|
||||
|
||||
int CustomFormatString(char* buf, size_t buf_size, const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
#ifdef IMGUI_USE_STB_SPRINTF
|
||||
int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
|
||||
#else
|
||||
int w = vsnprintf(buf, buf_size, fmt, args);
|
||||
#endif
|
||||
va_end(args);
|
||||
if (buf == NULL) return w;
|
||||
if (w == -1 || w >= (int)buf_size) w = (int)buf_size - 1;
|
||||
buf[w] = 0;
|
||||
return w;
|
||||
}
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
absl::Status PaletteEditor::Update() {
|
||||
for (int i = 0; i < 11; ++i) {
|
||||
if (ImGui::TreeNode(kPaletteCategoryNames[i].data())) {
|
||||
auto size = rom_.GetPaletteGroup(kPaletteGroupNames[i].data()).size;
|
||||
auto palettes = rom_.GetPaletteGroup(kPaletteGroupNames[i].data());
|
||||
for (int j = 0; j < size; j++) {
|
||||
ImGui::Text("%d", j);
|
||||
auto palette = palettes[j];
|
||||
for (int n = 0; n < size; n++) {
|
||||
ImGui::PushID(n);
|
||||
if ((n % 8) != 0)
|
||||
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
||||
namespace {
|
||||
void DrawPaletteTooltips(gfx::SNESPalette& palette, int size) {}
|
||||
|
||||
ImGuiColorEditFlags palette_button_flags =
|
||||
ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker;
|
||||
if (ImGui::ColorButton("##palette", palette[n].RGB(),
|
||||
palette_button_flags, ImVec2(20, 20)))
|
||||
current_color_ =
|
||||
ImVec4(palette[n].rgb.x, palette[n].rgb.y, palette[n].rgb.z,
|
||||
current_color_.w); // Preserve alpha!
|
||||
using namespace ImGui;
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void PaletteEditor::DrawPaletteGroup(int i) {
|
||||
const int palettesPerRow = 4;
|
||||
ImGui::BeginTable("palette_table", palettesPerRow,
|
||||
ImGuiTableFlags_BordersOuter | ImGuiTableFlags_Resizable);
|
||||
|
||||
auto size = rom_.GetPaletteGroup(kPaletteGroupNames[i].data()).size();
|
||||
auto palettes = rom_.GetPaletteGroup(kPaletteGroupNames[i].data());
|
||||
for (int j = 0; j < size; j++) {
|
||||
if (j % palettesPerRow == 0) {
|
||||
ImGui::TableNextRow();
|
||||
}
|
||||
ImGui::TableSetColumnIndex(j % palettesPerRow);
|
||||
ImGui::Text("%d", j);
|
||||
|
||||
auto palette = palettes[j];
|
||||
auto pal_size = palette.size_;
|
||||
|
||||
for (int n = 0; n < pal_size; n++) {
|
||||
ImGui::PushID(n);
|
||||
if ((n % 8) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
||||
|
||||
std::string popupId = kPaletteCategoryNames[i].data() +
|
||||
std::to_string(j) + "_" + std::to_string(n);
|
||||
if (ImGui::ColorButton(popupId.c_str(), palette[n].RGB(),
|
||||
palette_button_flags)) {
|
||||
if (ImGui::ColorEdit4(popupId.c_str(), palette[n].ToFloatArray(),
|
||||
palette_button_flags))
|
||||
current_color_ =
|
||||
ImVec4(palette[n].rgb.x, palette[n].rgb.y, palette[n].rgb.z,
|
||||
palette[n].rgb.w); // Preserve alpha!
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupContextItem(popupId.c_str())) {
|
||||
auto col = palette[n].ToFloatArray();
|
||||
if (ImGui::ColorEdit4(
|
||||
"Edit Color", col,
|
||||
ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha)) {
|
||||
// palette[n].rgb.x = current_color_rgba.x;
|
||||
// palette[n].rgb.y = current_color_rgba.y;
|
||||
// palette[n].rgb.z = current_color_rgba.z;
|
||||
// rom_.UpdatePaletteColor(kPaletteGroupNames[groupIndex].data(), j,
|
||||
// n, palette[n]);
|
||||
}
|
||||
if (Button("Copy as..", ImVec2(-1, 0))) OpenPopup("Copy");
|
||||
if (BeginPopup("Copy")) {
|
||||
int cr = IM_F32_TO_INT8_SAT(col[0]);
|
||||
int cg = IM_F32_TO_INT8_SAT(col[1]);
|
||||
int cb = IM_F32_TO_INT8_SAT(col[2]);
|
||||
char buf[64];
|
||||
CustomFormatString(buf, IM_ARRAYSIZE(buf), "(%.3ff, %.3ff, %.3ff)",
|
||||
col[0], col[1], col[2]);
|
||||
if (Selectable(buf)) SetClipboardText(buf);
|
||||
CustomFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d)", cr, cg, cb);
|
||||
if (Selectable(buf)) SetClipboardText(buf);
|
||||
CustomFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", cr, cg,
|
||||
cb);
|
||||
if (Selectable(buf)) SetClipboardText(buf);
|
||||
EndPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
absl::Status PaletteEditor::Update() {
|
||||
for (int i = 0; i < kNumPalettes; ++i) {
|
||||
if (ImGui::TreeNode(kPaletteCategoryNames[i].data())) {
|
||||
DrawPaletteGroup(i);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
@@ -49,13 +128,12 @@ void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) {
|
||||
|
||||
// Generate a default palette. The palette will persist and can be edited.
|
||||
static bool init = false;
|
||||
static ImVec4 saved_palette[256] = {};
|
||||
if (loaded && !init) {
|
||||
for (int n = 0; n < palette.size_; n++) {
|
||||
saved_palette[n].x = palette.GetColor(n).rgb.x / 255;
|
||||
saved_palette[n].y = palette.GetColor(n).rgb.y / 255;
|
||||
saved_palette[n].z = palette.GetColor(n).rgb.z / 255;
|
||||
saved_palette[n].w = 255; // Alpha
|
||||
saved_palette_[n].x = palette.GetColor(n).rgb.x / 255;
|
||||
saved_palette_[n].y = palette.GetColor(n).rgb.y / 255;
|
||||
saved_palette_[n].z = palette.GetColor(n).rgb.z / 255;
|
||||
saved_palette_[n].w = 255; // Alpha
|
||||
}
|
||||
init = true;
|
||||
}
|
||||
@@ -68,9 +146,9 @@ void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) {
|
||||
ImGui::OpenPopup("mypicker");
|
||||
backup_color = color;
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("mypicker")) {
|
||||
ImGui::Text("Current Overworld Palette");
|
||||
ImGui::Separator();
|
||||
TEXT_WITH_SEPARATOR("Current Overworld Palette");
|
||||
ImGui::ColorPicker4("##picker", (float*)&color,
|
||||
misc_flags | ImGuiColorEditFlags_NoSidePreview |
|
||||
ImGuiColorEditFlags_NoSmallPreview);
|
||||
@@ -94,25 +172,22 @@ void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) {
|
||||
color = backup_color;
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Palette");
|
||||
for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) {
|
||||
for (int n = 0; n < IM_ARRAYSIZE(saved_palette_); n++) {
|
||||
ImGui::PushID(n);
|
||||
if ((n % 8) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
||||
|
||||
ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha |
|
||||
ImGuiColorEditFlags_NoPicker |
|
||||
ImGuiColorEditFlags_NoTooltip;
|
||||
if (ImGui::ColorButton("##palette", saved_palette[n],
|
||||
palette_button_flags, ImVec2(20, 20)))
|
||||
color = ImVec4(saved_palette[n].x, saved_palette[n].y,
|
||||
saved_palette[n].z, color.w); // Preserve alpha!
|
||||
if (ImGui::ColorButton("##palette", saved_palette_[n],
|
||||
palette_button_flags_2, ImVec2(20, 20)))
|
||||
color = ImVec4(saved_palette_[n].x, saved_palette_[n].y,
|
||||
saved_palette_[n].z, color.w); // Preserve alpha!
|
||||
|
||||
if (ImGui::BeginDragDropTarget()) {
|
||||
if (const ImGuiPayload* payload =
|
||||
ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
|
||||
memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
|
||||
memcpy((float*)&saved_palette_[n], payload->Data, sizeof(float) * 3);
|
||||
if (const ImGuiPayload* payload =
|
||||
ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
|
||||
memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
|
||||
memcpy((float*)&saved_palette_[n], payload->Data, sizeof(float) * 4);
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,15 +13,18 @@ namespace yaze {
|
||||
namespace app {
|
||||
namespace editor {
|
||||
|
||||
constexpr int kNumPalettes = 11;
|
||||
|
||||
static constexpr absl::string_view kPaletteCategoryNames[] = {
|
||||
"Sword", "Shield", "Clothes", "World Colors",
|
||||
"Area Colors", "Enemies", "Dungeons", "World Map",
|
||||
"Dungeon Map", "Triforce", "Crystal"};
|
||||
|
||||
static constexpr absl::string_view kPaletteGroupNames[] = {
|
||||
"swords", "shields", "armors", "ow_main",
|
||||
"ow_aux", "global_sprites", "dungeon_main", "ow_mini_map",
|
||||
"ow_mini_map", "3d_object", "3d_object"};
|
||||
"swords", "shields", "armors", "ow_main",
|
||||
"ow_aux", "global_sprites", "dungeon_main", "ow_mini_map",
|
||||
"ow_mini_map", "3d_object", "3d_object"};
|
||||
|
||||
|
||||
class PaletteEditor {
|
||||
public:
|
||||
@@ -31,8 +34,17 @@ class PaletteEditor {
|
||||
auto SetupROM(ROM& rom) { rom_ = rom; }
|
||||
|
||||
private:
|
||||
void DrawPaletteGroup(int i);
|
||||
|
||||
ImVec4 saved_palette_[256] = {};
|
||||
ImVec4 current_color_;
|
||||
ROM rom_;
|
||||
|
||||
ImGuiColorEditFlags palette_button_flags =
|
||||
ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoTooltip;
|
||||
ImGuiColorEditFlags palette_button_flags_2 = ImGuiColorEditFlags_NoAlpha |
|
||||
ImGuiColorEditFlags_NoPicker |
|
||||
ImGuiColorEditFlags_NoTooltip;
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
|
||||
@@ -190,7 +190,7 @@ SDL_Palette* SNESPalette::GetSDL_Palette() {
|
||||
return sdl_palette.get();
|
||||
}
|
||||
|
||||
PaletteGroup::PaletteGroup(uint8_t mSize) : size(mSize) {}
|
||||
PaletteGroup::PaletteGroup(uint8_t mSize) : size_(mSize) {}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace app
|
||||
|
||||
@@ -47,10 +47,18 @@ struct SNESColor {
|
||||
void setSNES(uint16_t);
|
||||
void setTransparent(bool t) { transparent = t; }
|
||||
|
||||
auto RGB() {
|
||||
return ImVec4(rgb.x / 255, rgb.y / 255, rgb.z / 255, rgb.w);
|
||||
auto RGB() { return ImVec4(rgb.x / 255, rgb.y / 255, rgb.z / 255, rgb.w); }
|
||||
|
||||
float* ToFloatArray() const {
|
||||
static std::vector<float> colorArray(4);
|
||||
colorArray[0] = rgb.x / 255.0f;
|
||||
colorArray[1] = rgb.y / 255.0f;
|
||||
colorArray[2] = rgb.z / 255.0f;
|
||||
colorArray[3] = rgb.w;
|
||||
return colorArray.data();
|
||||
}
|
||||
|
||||
bool modified = false;
|
||||
bool transparent = false;
|
||||
uint16_t snes = 0;
|
||||
ImVec4 rgb;
|
||||
@@ -82,6 +90,7 @@ class SNESPalette {
|
||||
SDL_Palette* GetSDL_Palette();
|
||||
|
||||
int size_ = 0;
|
||||
auto size() const { return colors.size(); }
|
||||
std::vector<SNESColor> colors;
|
||||
};
|
||||
|
||||
@@ -90,23 +99,24 @@ struct PaletteGroup {
|
||||
explicit PaletteGroup(uint8_t mSize);
|
||||
void AddPalette(SNESPalette pal) {
|
||||
palettes.emplace_back(pal);
|
||||
size = palettes.size();
|
||||
size_ = palettes.size();
|
||||
}
|
||||
void AddColor(SNESColor color) {
|
||||
if (size == 0) {
|
||||
if (size_ == 0) {
|
||||
SNESPalette empty_pal;
|
||||
palettes.emplace_back(empty_pal);
|
||||
}
|
||||
palettes[0].AddColor(color);
|
||||
}
|
||||
SNESPalette operator[](int i) {
|
||||
if (i > size) {
|
||||
if (i > size_) {
|
||||
std::cout << "PaletteGroup: Index out of bounds" << std::endl;
|
||||
return palettes[0];
|
||||
}
|
||||
return palettes[i];
|
||||
}
|
||||
int size = 0;
|
||||
int size_ = 0;
|
||||
auto size() const { return palettes.size(); }
|
||||
std::vector<SNESPalette> palettes;
|
||||
};
|
||||
|
||||
|
||||
@@ -816,6 +816,54 @@ void ROM::LoadAllPalettes() {
|
||||
}
|
||||
}
|
||||
|
||||
void ROM::SaveAllPalettes() {
|
||||
// Iterate through all palette_groups_
|
||||
for (auto& group : palette_groups_) {
|
||||
const std::string& groupName = group.first;
|
||||
auto& palettes = group.second;
|
||||
|
||||
// Iterate through all palettes in the group
|
||||
for (size_t i = 0; i < palettes.size(); ++i) {
|
||||
auto palette = palettes[i];
|
||||
|
||||
// Iterate through all colors in the palette
|
||||
for (size_t j = 0; j < palette.size(); ++j) {
|
||||
gfx::SNESColor color = palette[j];
|
||||
|
||||
// If the color is modified, save the color to the ROM
|
||||
if (color.modified) {
|
||||
WriteColor(GetPaletteAddress(groupName, i, j), color);
|
||||
color.modified = false; // Reset the modified flag after saving
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ROM::WriteColor(uint32_t address, const gfx::SNESColor& color) {
|
||||
uint16_t bgr = ((color.snes >> 10) & 0x1F) | ((color.snes & 0x1F) << 10) |
|
||||
(color.snes & 0x7C00);
|
||||
|
||||
// Write the 16-bit color value to the ROM at the specified address
|
||||
rom_data_[address] = static_cast<uint8_t>(bgr & 0xFF);
|
||||
rom_data_[address + 1] = static_cast<uint8_t>((bgr >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
uint32_t ROM::GetPaletteAddress(const std::string& groupName,
|
||||
size_t paletteIndex, size_t colorIndex) const {
|
||||
// Retrieve the base address for the palette group
|
||||
uint32_t baseAddress = paletteGroupBaseAddresses.at(groupName);
|
||||
|
||||
// Retrieve the number of colors for each palette in the group
|
||||
size_t colorsPerPalette = paletteGroupColorCounts.at(groupName);
|
||||
|
||||
// Calculate the address for the specified color in the ROM
|
||||
uint32_t address =
|
||||
baseAddress + (paletteIndex * colorsPerPalette * 2) + (colorIndex * 2);
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
absl::Status ROM::ApplyAssembly(const absl::string_view& filename,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@@ -72,6 +73,48 @@ struct CompressionPiece {
|
||||
using CompressionPiece = struct CompressionPiece;
|
||||
using CompressionPiecePointer = std::shared_ptr<CompressionPiece>;
|
||||
|
||||
const std::map<std::string, uint32_t> paletteGroupBaseAddresses = {
|
||||
{"ow_main", core::overworldPaletteMain},
|
||||
{"ow_aux", core::overworldPaletteAuxialiary},
|
||||
{"ow_animated", core::overworldPaletteAnimated},
|
||||
{"hud", core::hudPalettes},
|
||||
{"global_sprites",
|
||||
core::globalSpritePalettesLW}, // Assuming LW is the first palette
|
||||
{"armors", core::armorPalettes},
|
||||
{"swords", core::swordPalettes},
|
||||
{"shields", core::shieldPalettes},
|
||||
{"sprites_aux1", core::spritePalettesAux1},
|
||||
{"sprites_aux2", core::spritePalettesAux2},
|
||||
{"sprites_aux3", core::spritePalettesAux3},
|
||||
{"dungeon_main", core::dungeonMainPalettes},
|
||||
{"grass", core::hardcodedGrassLW}, // Assuming LW is the first color
|
||||
{"3d_object",
|
||||
core::triforcePalette}, // Assuming triforcePalette is the first palette
|
||||
{"ow_mini_map", core::overworldMiniMapPalettes},
|
||||
};
|
||||
|
||||
const std::map<std::string, size_t> paletteGroupColorCounts = {
|
||||
{"ow_main", 35},
|
||||
{"ow_aux", 21},
|
||||
{"ow_animated", 7},
|
||||
{"hud", 32},
|
||||
{"global_sprites", 60}, // Assuming both LW and DW
|
||||
// palettes have the same
|
||||
// color count
|
||||
{"armors", 15},
|
||||
{"swords", 3},
|
||||
{"shields", 4},
|
||||
{"sprites_aux1", 7},
|
||||
{"sprites_aux2", 7},
|
||||
{"sprites_aux3", 7},
|
||||
{"dungeon_main", 90},
|
||||
{"grass", 1}, // Assuming grass palettes are
|
||||
// individual colors
|
||||
{"3d_object", 8}, // Assuming both triforcePalette and crystalPalette have
|
||||
// the same color count
|
||||
{"ow_mini_map", 128},
|
||||
};
|
||||
|
||||
class ROM {
|
||||
public:
|
||||
absl::StatusOr<Bytes> Compress(const int start, const int length,
|
||||
@@ -91,6 +134,11 @@ class ROM {
|
||||
absl::Status LoadFromBytes(const Bytes& data);
|
||||
void LoadAllPalettes();
|
||||
|
||||
void SaveAllPalettes();
|
||||
|
||||
uint32_t GetPaletteAddress(const std::string& groupName, size_t paletteIndex,
|
||||
size_t colorIndex) const;
|
||||
|
||||
absl::Status SaveToFile();
|
||||
|
||||
gfx::SNESColor ReadColor(int offset);
|
||||
@@ -98,6 +146,7 @@ class ROM {
|
||||
|
||||
void Write(int addr, int value);
|
||||
void WriteShort(int addr, int value);
|
||||
void WriteColor(uint32_t address, const gfx::SNESColor& color);
|
||||
|
||||
absl::Status ApplyAssembly(const absl::string_view& filename,
|
||||
size_t patch_size);
|
||||
|
||||
Reference in New Issue
Block a user