Add CgxViewer, update GraphicsEditor

This commit is contained in:
scawful
2023-07-18 21:55:23 -04:00
parent 2b0c550274
commit df8443152b
10 changed files with 271 additions and 102 deletions

View File

@@ -44,6 +44,11 @@ set(
app/gui/color.cc app/gui/color.cc
) )
set(
YAZE_VIEWER_SRC
app/viewer/cgx_viewer.cc
)
# executable creation --------------------------------------------------------- # executable creation ---------------------------------------------------------
add_executable( add_executable(
@@ -55,6 +60,7 @@ add_executable(
${YAZE_APP_GFX_SRC} ${YAZE_APP_GFX_SRC}
${YAZE_APP_ZELDA3_SRC} ${YAZE_APP_ZELDA3_SRC}
${YAZE_GUI_SRC} ${YAZE_GUI_SRC}
${YAZE_VIEWER_SRC}
# ${ASAR_STATIC_SRC} # ${ASAR_STATIC_SRC}
# ${SNES_SPC_SOURCES} # ${SNES_SPC_SOURCES}
${IMGUI_SRC} ${IMGUI_SRC}

View File

@@ -33,6 +33,19 @@
ImGui::TableNextColumn(); \ ImGui::TableNextColumn(); \
ImGui::Text(w); ImGui::Text(w);
#define BEGIN_TABLE(l, n, f) if (ImGui::BeginTable(l, n, f, ImVec2(0, 0))) {
#define SETUP_COLUMN(l) ImGui::TableSetupColumn(l);
#define TABLE_HEADERS() \
ImGui::TableHeadersRow(); \
ImGui::TableNextRow();
#define NEXT_COLUMN() ImGui::TableNextColumn();
#define END_TABLE() \
ImGui::EndTable(); \
}
#define PRINT_IF_ERROR(expression) \ #define PRINT_IF_ERROR(expression) \
{ \ { \
auto error = expression; \ auto error = expression; \
@@ -66,7 +79,7 @@
#define APPEND_NUMBER_INNER(expression, number) expression##number #define APPEND_NUMBER_INNER(expression, number) expression##number
#define TEXT_WITH_SEPARATOR(text) \ #define TEXT_WITH_SEPARATOR(text) \
ImGui::Text(text); \ ImGui::Text(text); \
ImGui::Separator(); ImGui::Separator();
using ushort = unsigned short; using ushort = unsigned short;

View File

@@ -19,31 +19,37 @@ namespace app {
namespace editor { namespace editor {
absl::Status GraphicsEditor::Update() { absl::Status GraphicsEditor::Update() {
if (ImGui::BeginTable("#gfxEditTable", 2, gfx_edit_flags, ImVec2(0, 0))) { BEGIN_TABLE("#gfxEditTable", 2, gfx_edit_flags)
ImGui::TableSetupColumn("Bin Importer", ImGuiTableColumnFlags_WidthStretch, SETUP_COLUMN("Bin Importer")
ImGui::GetContentRegionAvail().x); SETUP_COLUMN("Graphics Manager")
ImGui::TableSetupColumn("Graphics Manager"); TABLE_HEADERS()
ImGui::TableHeadersRow(); NEXT_COLUMN()
ImGui::TableNextRow();
ImGui::TableNextColumn();
RETURN_IF_ERROR(DrawImport())
ImGui::TableNextColumn(); TAB_BAR("##GfxTabBar")
TAB_ITEM("File Import")
RETURN_IF_ERROR(DrawFileImport())
END_TAB_ITEM()
TAB_ITEM("Clipboard Import")
RETURN_IF_ERROR(DrawClipboardImport())
END_TAB_ITEM()
END_TAB_BAR()
ImGui::Text("Graphics");
ImGui::Separator();
RETURN_IF_ERROR(DrawDecompressedData())
ImGui::EndTable(); NEXT_COLUMN()
} RETURN_IF_ERROR(DrawMemoryEditor())
END_TABLE()
return absl::OkStatus(); return absl::OkStatus();
} }
absl::Status GraphicsEditor::DrawImport() { absl::Status GraphicsEditor::DrawFileImport() {
static int size = 0; static int size = 0;
static char filePath[256] = "";
static bool open = false;
ImGui::SetNextItemWidth(350.f); ImGui::SetNextItemWidth(350.f);
ImGui::InputText("File", filePath, sizeof(filePath)); ImGui::InputText("File", file_path_, sizeof(file_path_));
ImGui::SameLine();
// Open the file dialog when the user clicks the "Browse" button // Open the file dialog when the user clicks the "Browse" button
if (ImGui::Button("Browse")) { if (ImGui::Button("Browse")) {
ImGuiFileDialog::Instance()->OpenDialog("ImportDlgKey", "Choose File", ImGuiFileDialog::Instance()->OpenDialog("ImportDlgKey", "Choose File",
@@ -52,35 +58,33 @@ absl::Status GraphicsEditor::DrawImport() {
// Draw the file dialog // Draw the file dialog
if (ImGuiFileDialog::Instance()->Display("ImportDlgKey")) { if (ImGuiFileDialog::Instance()->Display("ImportDlgKey")) {
// If the user made a selection, copy the filename to the filePath buffer // If the user made a selection, copy the filename to the file_path_ buffer
if (ImGuiFileDialog::Instance()->IsOk()) { if (ImGuiFileDialog::Instance()->IsOk()) {
strncpy(filePath, ImGuiFileDialog::Instance()->GetFilePathName().c_str(), strncpy(file_path_,
sizeof(filePath)); ImGuiFileDialog::Instance()->GetFilePathName().c_str(),
RETURN_IF_ERROR(temp_rom_.LoadFromFile(filePath)) sizeof(file_path_));
open = true; RETURN_IF_ERROR(temp_rom_.LoadFromFile(file_path_))
is_open_ = true;
} }
// Close the modal // Close the modal
ImGuiFileDialog::Instance()->Close(); ImGuiFileDialog::Instance()->Close();
} }
if (open) {
static MemoryEditor mem_edit;
mem_edit.DrawWindow(filePath, (void *)&temp_rom_, temp_rom_.size());
}
gui::InputHex("Offset", &current_offset_); gui::InputHex("Offset", &current_offset_);
gui::InputHex("Size ", &size); gui::InputHex("Size ", &size);
gui::InputHex("Palette ", &current_palette_); gui::InputHex("Palette ", &current_palette_);
if (ImGui::Button("Super Donkey")) { if (ImGui::Button("Super Donkey Offsets")) {
current_offset_ = 0x98219; current_offset_ = 0x98219;
size = 0x30000; size = 0x30000;
} }
ImGui::SameLine();
if (ImGui::Button("Import")) { if (ImGui::Button("Import")) {
if (strlen(filePath) > 0) { if (strlen(file_path_) > 0) {
// Add your importing code here, using filePath and offset as parameters // Add your importing code here, using file_path_ and offset as parameters
RETURN_IF_ERROR(DecompressImportData(size)) RETURN_IF_ERROR(DecompressImportData(size))
} else { } else {
// Show an error message if no file has been selected // Show an error message if no file has been selected
@@ -88,6 +92,32 @@ absl::Status GraphicsEditor::DrawImport() {
} }
} }
return absl::OkStatus();
}
absl::Status GraphicsEditor::DrawClipboardImport() {
static Bytes clipboard_data;
if (!is_open_) {
clipboard_data.resize(0x1000);
for (int i = 0; i < 0x1000; i++) clipboard_data.push_back(0x00);
RETURN_IF_ERROR(temp_rom_.LoadFromBytes(clipboard_data))
is_open_ = true;
}
return absl::OkStatus();
}
absl::Status GraphicsEditor::DrawMemoryEditor() {
std::string title = "Memory Editor";
if (is_open_) {
static MemoryEditor mem_edit;
mem_edit.DrawWindow(title.data(), (void *)&temp_rom_, temp_rom_.size());
}
return absl::OkStatus();
}
absl::Status GraphicsEditor::DrawDecompressedData() {
if (ImGuiID child_id = ImGui::GetID((void *)(intptr_t)2); if (ImGuiID child_id = ImGui::GetID((void *)(intptr_t)2);
ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true, ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true,
ImGuiWindowFlags_AlwaysVerticalScrollbar)) { ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
@@ -99,17 +129,16 @@ absl::Status GraphicsEditor::DrawImport() {
import_canvas_.DrawOverlay(); import_canvas_.DrawOverlay();
} }
ImGui::EndChild(); ImGui::EndChild();
return absl::OkStatus(); return absl::OkStatus();
} }
absl::Status GraphicsEditor::DecompressImportData(int size) { absl::Status GraphicsEditor::DecompressImportData(int size) {
ASSIGN_OR_RETURN(import_data_, temp_rom_.Decompress(current_offset_, size)) ASSIGN_OR_RETURN(import_data_, temp_rom_.Decompress(current_offset_, size))
std::cout << "Size of import data" << import_data_.size() << std::endl; std::cout << "Size of import data " << import_data_.size() << std::endl;
Bytes new_sheet; Bytes new_sheet;
bitmap_.Create(core::kTilesheetWidth, 0x2000, core::kTilesheetDepth, bitmap_.Create(core::kTilesheetWidth, 0x2000, core::kTilesheetDepth,
import_data_.data(), 0x1000); import_data_.data(), size);
if (rom_.isLoaded()) { if (rom_.isLoaded()) {
auto palette_group = rom_.GetPaletteGroup("ow_main"); auto palette_group = rom_.GetPaletteGroup("ow_main");

View File

@@ -46,13 +46,20 @@ class GraphicsEditor {
void SetupROM(ROM &rom) { rom_ = rom; } void SetupROM(ROM &rom) { rom_ = rom; }
private: private:
absl::Status DrawImport(); absl::Status DrawFileImport();
absl::Status DrawClipboardImport();
absl::Status DrawMemoryEditor();
absl::Status DrawDecompressedData();
absl::Status DecompressImportData(int size); absl::Status DecompressImportData(int size);
int current_offset_ = 0; int current_offset_ = 0;
int current_size_ = 0; int current_size_ = 0;
int current_palette_ = 0; int current_palette_ = 0;
bool gfx_loaded_ = false; bool gfx_loaded_ = false;
bool is_open_ = false;
char file_path_[256];
ROM rom_; ROM rom_;
ROM temp_rom_; ROM temp_rom_;
@@ -65,6 +72,7 @@ class GraphicsEditor {
PaletteEditor palette_editor_; PaletteEditor palette_editor_;
gfx::SNESPalette palette_; gfx::SNESPalette palette_;
MemoryEditor memory_editor_;
ImGuiTableFlags gfx_edit_flags = ImGuiTableFlags_Reorderable | ImGuiTableFlags gfx_edit_flags = ImGuiTableFlags_Reorderable |
ImGuiTableFlags_Resizable | ImGuiTableFlags_Resizable |

View File

@@ -60,6 +60,26 @@ char* Convert(const snes_palette pal) {
return toret; return toret;
} }
SNESColor GetCgxColor(short color) {
ImVec4 rgb;
rgb.x = (color & 0x1F) * 8;
rgb.y = ((color & 0x3E0) >> 5) * 8;
rgb.z = ((color & 0x7C00) >> 10) * 8;
SNESColor toret;
toret.setRgb(rgb);
return toret;
}
std::vector<SNESColor> GetColFileData(uchar* data) {
std::vector<SNESColor> colors;
for (int i = 0; i < 512; i += 2) {
colors[i / 2] = GetCgxColor((short)((data[i + 1] << 8) + data[i]));
}
return colors;
}
// ============================================================================ // ============================================================================
SNESColor::SNESColor() : rgb(ImVec4(0.f, 0.f, 0.f, 0.f)) {} SNESColor::SNESColor() : rgb(ImVec4(0.f, 0.f, 0.f, 0.f)) {}

View File

@@ -66,6 +66,10 @@ struct SNESColor {
ImVec4 rgb; ImVec4 rgb;
}; };
SNESColor GetCgxColor(short color);
std::vector<SNESColor> GetColFileData(uchar* data);
class SNESPalette { class SNESPalette {
public: public:
SNESPalette() = default; SNESPalette() = default;

View File

@@ -643,6 +643,8 @@ absl::Status ROM::LoadFromBytes(const Bytes& data) {
"Could not load ROM: parameter `data` is empty."); "Could not load ROM: parameter `data` is empty.");
} }
rom_data_ = data; rom_data_ = data;
size_ = data.size();
is_loaded_ = true;
return absl::OkStatus(); return absl::OkStatus();
} }

View File

@@ -0,0 +1,113 @@
#include "cgx_viewer.h"
#include <fstream>
#include <iostream>
#include <vector>
#include "app/gfx/bitmap.h"
#include "app/gfx/snes_palette.h"
#include "app/gfx/snes_tile.h"
namespace yaze {
namespace app {
namespace viewer {
void CgxViewer::Update() {
static int current_bpp = 1;
// ImGui::Combo("BPP", current_bpp, "0\0 1\0 2\0 3\0", 4, 4);
LoadColFile();
LoadGfx(current_bpp);
LoadScr();
}
void CgxViewer::LoadColFile() {
uchar data[512];
std::vector<gfx::SNESColor> colors;
for (int i = 0; i < 512; i += 2) {
colors[i / 2] = gfx::GetCgxColor((short)((data[i + 1] << 8) + data[i]));
}
}
void CgxViewer::LoadCgx(std::string pathfile) {
unsigned char* ptr = rawData.data();
for (int i = 0; i < 0x40000; i++) {
ptr[i] = 0;
rawData[i] = 0;
}
std::ifstream fs(pathfile, std::ios::binary);
std::vector<unsigned char> data((std::istreambuf_iterator<char>(fs)),
std::istreambuf_iterator<char>());
fs.close();
int matchingPos = -1;
bool matched = false;
for (int i = 0; i < data.size(); i++) {
if (matched) {
break;
}
rawData[i] = data[i];
for (int j = 0; j < matchBytes.size(); j++) {
if (data[i + j] == matchBytes[j]) {
if (j == matchBytes.size() - 1) {
matchingPos = i;
matched = true;
break;
}
} else {
break;
}
}
}
char buffer[10];
sprintf(buffer, "%X4", matchingPos);
label1_text = "CGX In Folder L : " + std::string(buffer);
LoadGfx(current_selection_);
}
struct GFX_Class {
unsigned char* indexedPointer;
} GFX;
struct PictureBox_Class {
void (*Refresh)();
} pictureBox1;
void CgxViewer::LoadGfx(int comboBpp) {
if (comboBpp == 0) {
bpp_ = 4;
} else if (comboBpp == 1) {
bpp_ = 2;
} else if (comboBpp == 2) {
bpp_ = 8;
} else if (comboBpp == 3) {
bpp_ = 40;
unsigned char* ptr = GFX.indexedPointer;
for (int i = 0; i < rawData.size(); i++) {
ptr[i] = rawData[i];
}
RefreshPalettes();
pictureBox1.Refresh();
return;
}
unsigned char* ptr = GFX.indexedPointer;
Bytes rawBytes; // rawData.data()
std::vector<unsigned char> dd = gfx::SnesTo8bppSheet(rawBytes, bpp_);
for (int i = 0; i < dd.size(); i++) {
ptr[i] = dd[i];
}
RefreshPalettes();
pictureBox1.Refresh();
}
void CgxViewer::LoadScr() {}
void CgxViewer::RefreshPalettes() {}
} // namespace viewer
} // namespace app
} // namespace yaze

View File

@@ -0,0 +1,41 @@
#ifndef YAZE_APP_VIEWER_CGX_VIEWER_H
#define YAZE_APP_VIEWER_CGX_VIEWER_H
#include <fstream>
#include <iostream>
#include <vector>
#include "app/gfx/bitmap.h"
#include "app/gfx/snes_palette.h"
#include "app/gfx/snes_tile.h"
#include "app/rom.h"
namespace yaze {
namespace app {
namespace viewer {
class CgxViewer {
public:
void Update();
private:
void LoadColFile();
void LoadCgx(std::string pathfile);
void LoadGfx(int comboBpp);
void LoadScr();
void RefreshPalettes();
std::vector<unsigned char> matchBytes; // Assuming it's a vector of bytes.
std::string label1_text;
int bpp_;
int current_selection_;
ROM rawData;
};
} // namespace viewer
} // namespace app
} // namespace yaze
#endif // YAZE_APP_VIEWER_CGX_VIEWER_H

View File

@@ -1,67 +0,0 @@
#include <asar/interface-lib.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <array>
#include <cstdint>
#include <fstream>
#include <sstream>
#include <string>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "app/asm/script.h"
#include "app/core/constants.h"
#include "app/rom.h"
namespace yaze_test {
namespace asm_test {
using yaze::app::ROM;
using yaze::app::snes_asm::Script;
using ::testing::_;
using ::testing::ElementsAreArray;
using ::testing::Eq;
using ::testing::Return;
class MockScript : public Script {
public:
MOCK_METHOD(absl::Status, ApplyPatchToROM, (ROM & rom));
MOCK_METHOD(absl::Status, PatchOverworldMosaic,
(ROM & rom, char mosaic_tiles[yaze::app::core::kNumOverworldMaps],
int routine_offset, int hook_offset));
};
TEST(ASMTest, ApplyMosaicChangePatchOk) {
ROM rom;
MockScript script;
char mosaic_tiles[yaze::app::core::kNumOverworldMaps];
EXPECT_CALL(script, PatchOverworldMosaic(_, Eq(mosaic_tiles),
Eq(0x1301D0 + 0x138000), 0))
.WillOnce(Return(absl::OkStatus()));
EXPECT_CALL(script, ApplyPatchToROM(_)).WillOnce(Return(absl::OkStatus()));
EXPECT_THAT(
script.PatchOverworldMosaic(rom, mosaic_tiles, 0x1301D0 + 0x138000, 0),
absl::OkStatus());
EXPECT_THAT(script.ApplyPatchToROM(rom), absl::OkStatus());
}
TEST(ASMTest, NoPatchLoadedError) {
ROM rom;
MockScript script;
EXPECT_CALL(script, ApplyPatchToROM(_))
.WillOnce(Return(absl::InvalidArgumentError("No patch loaded!")));
EXPECT_THAT(script.ApplyPatchToROM(rom),
absl::InvalidArgumentError("No patch loaded!"));
}
} // namespace asm_test
} // namespace yaze_test