housekeeping and inventory menu

This commit is contained in:
scawful
2022-09-17 10:34:44 -05:00
parent 67a5f6bf68
commit a20b3fd240
17 changed files with 266 additions and 165 deletions

View File

@@ -36,12 +36,35 @@ set(
# Asar Assembly ---------------------------------------------------------------
add_subdirectory(lib/asar/src)
set(ASAR_GEN_EXE OFF)
set(ASAR_GEN_DLL ON)
set(ASAR_GEN_LIB OFF)
get_target_property(ASAR_INCLUDE_DIR asar-static INCLUDE_DIRECTORIES)
target_include_directories(asar-static PRIVATE ${ASAR_INCLUDE_DIR})
set(ASAR_GEN_EXE OFF)
set(ASAR_GEN_DLL ON)
set(ASAR_GEN_LIB ON)
set(ASAR_GEN_EXE_TEST OFF)
set(ASAR_GEN_DLL_TEST OFF)
set(ASAR_STATIC_SRC
"lib/asar/src/asar/interface-lib.cpp"
"lib/asar/src/asar/addr2line.cpp"
"lib/asar/src/asar/arch-65816.cpp"
"lib/asar/src/asar/arch-spc700.cpp"
"lib/asar/src/asar/arch-superfx.cpp"
"lib/asar/src/asar/assembleblock.cpp"
"lib/asar/src/asar/crc32.cpp"
"lib/asar/src/asar/libcon.cpp"
"lib/asar/src/asar/libsmw.cpp"
"lib/asar/src/asar/libstr.cpp"
"lib/asar/src/asar/macro.cpp"
"lib/asar/src/asar/main.cpp"
"lib/asar/src/asar/asar_math.cpp"
"lib/asar/src/asar/virtualfile.cpp"
"lib/asar/src/asar/warnings.cpp"
"lib/asar/src/asar/errors.cpp"
"lib/asar/src/asar/platform/file-helpers.cpp"
"lib/asar/src/asar/platform/linux/file-helpers-linux.cpp"
)
# yaze source files -----------------------------------------------------------
set(
YAZE_APP_CORE_SRC
@@ -86,6 +109,7 @@ set(
gui/input.cc
gui/style.cc
gui/widgets.cc
gui/color.cc
)
add_executable(
@@ -99,7 +123,7 @@ add_executable(
${YAZE_APP_ZELDA3_SRC}
${YAZE_GUI_SRC}
${IMGUI_SRC}
lib/asar/src/asar-dll-bindings/c/asardll.c
${ASAR_STATIC_SRC}
)
target_include_directories(
@@ -111,7 +135,7 @@ target_include_directories(
${PNG_INCLUDE_DIRS}
${SDL2_INCLUDE_DIR}
${GLEW_INCLUDE_DIRS}
lib/asar/src/asar-dll-bindings/c
lib/asar/src/
)
set(SDL_TARGETS SDL2::SDL2)
@@ -130,7 +154,10 @@ target_link_libraries(
${OPENGL_LIBRARIES}
${CMAKE_DL_LIBS}
ImGui
asar-static
)
target_compile_definitions(yaze PRIVATE "linux")
target_compile_definitions(yaze PRIVATE "stricmp=strcasecmp")
set_target_properties(yaze
PROPERTIES
@@ -155,7 +182,6 @@ add_executable(
${YAZE_APP_ZELDA3_SRC}
${YAZE_GUI_SRC}
${IMGUI_SRC}
lib/asar/src/asar-dll-bindings/c/asardll.c
)
target_include_directories(
@@ -167,7 +193,7 @@ target_include_directories(
${PNG_INCLUDE_DIRS}
${SDL2_INCLUDE_DIR}
${GLEW_INCLUDE_DIRS}
lib/asar/src/asar-dll-bindings/c
${ASAR_STATIC_SRC}
)
target_link_libraries(
@@ -179,6 +205,7 @@ target_link_libraries(
${OPENGL_LIBRARIES}
${CMAKE_DL_LIBS}
delta-service
asar-static
ImGui
)

View File

@@ -1,6 +1,6 @@
#include "script.h"
#include <asardll.h>
#include <asar/interface-lib.h>
#include <array>
#include <cstdint>
@@ -20,49 +20,13 @@ namespace yaze {
namespace app {
namespace snes_asm {
std::string GenerateBytePool(char mosaic_tiles[core::kNumOverworldMaps]) {
std::string to_return = "";
int column = 0;
for (int i = 0; i < core::kNumOverworldMaps; ++i) {
std::string to_add = "";
// if start of line, define byte
if (i == 0 || i % 8 == 0) {
to_add += " db ";
}
// set byte
to_add += "$00";
if (mosaic_tiles[i] > 0) {
if (i == 0 || i % 8 == 0) {
to_add = " db $01";
} else {
to_add = "$01";
}
}
// newline or comma separated
if (column == 7) {
column = 0;
to_add += " \n";
} else {
column++;
to_add += ", ";
}
to_return += to_add;
}
return to_return;
}
absl::Status Script::ApplyPatchToROM(ROM &rom) {
if (patch_contents_.empty() || patch_filename_.empty()) {
return absl::InvalidArgumentError("No patch loaded!");
}
char *data = (char *)rom.data();
int size = rom.GetSize();
int count = 0;
auto data = (char *)rom.data();
int size = rom.size();
if (!asar_patch(patch_filename_.c_str(), data, patch_size_, &size)) {
auto asar_error = asar_geterrors(&count);
auto full_error = asar_error->fullerrdata;
@@ -71,43 +35,37 @@ absl::Status Script::ApplyPatchToROM(ROM &rom) {
return absl::OkStatus();
}
absl::Status Script::GenerateMosaicChangeAssembly(
absl::Status Script::PatchOverworldMosaic(
ROM &rom, char mosaic_tiles[core::kNumOverworldMaps], int routine_offset,
int hook_offset) {
for (int i = 0; i < core::kNumOverworldMaps; i++) {
if (mosaic_tiles[i]) {
rom[core::overworldCustomMosaicArray + i] = 0x01;
} else {
rom[core::overworldCustomMosaicArray + i] = 0x00;
}
}
std::fstream file("assets/asm/mosaic_change.asm",
std::ios::out | std::ios::in);
if (!file.is_open()) {
return absl::InvalidArgumentError(
"Couldn't open mosaic change template file");
"Unable to open mosaic change assembly source");
}
std::stringstream assembly;
assembly << file.rdbuf();
file.close();
auto assembly_string = assembly.str();
if (!core::StringReplace(assembly_string, "<HOOK>", kMosaicChangeOffset)) {
return absl::InternalError(
"Mosaic template did not have proper `<HOOK>` to replace.");
}
if (!core::StringReplace(
assembly_string, "<EXPANDED_SPACE>",
absl::StrFormat("$%x", routine_offset + kSNESToPCOffset))) {
return absl::InternalError(
"Mosaic template did not have proper `<EXPANDED_SPACE>` to replace.");
}
assembly_string += GenerateBytePool(mosaic_tiles);
patch_contents_ = assembly_string;
patch_filename_ = "assets/asm/mosaic_change_generated.asm";
std::ofstream new_file(patch_filename_, std::ios::out);
if (new_file.is_open()) {
new_file.write(assembly_string.c_str(), assembly_string.size());
new_file.close();
}
return ApplyPatchToROM(rom);
}

View File

@@ -1,7 +1,7 @@
#ifndef YAZE_APP_ASM_SCRIPT_H
#define YAZE_APP_ASM_SCRIPT_H
#include <asardll.h>
#include <asar/interface-lib.h>
#include <array>
#include <cstdint>
@@ -27,17 +27,15 @@ class ScriptTemplate {
public:
virtual ~ScriptTemplate() = default;
virtual absl::Status ApplyPatchToROM(ROM& rom) = 0;
virtual absl::Status GenerateMosaicChangeAssembly(
virtual absl::Status PatchOverworldMosaic(
ROM& rom, char mosaic_tiles[core::kNumOverworldMaps], int routine_offset,
int hook_offset = 0) = 0;
};
class Script : public ScriptTemplate {
public:
Script() { asar_init_with_dll_path("assets/libasar.dll"); }
absl::Status ApplyPatchToROM(ROM& rom) override;
absl::Status GenerateMosaicChangeAssembly(
absl::Status PatchOverworldMosaic(
ROM& rom, char mosaic_tiles[core::kNumOverworldMaps], int routine_offset,
int hook_offset = 0) override;

View File

@@ -482,7 +482,7 @@ constexpr int customAreaSpecificBGPalette =
constexpr int customAreaSpecificBGASM = 0x140150;
constexpr int customAreaSpecificBGEnabled =
0x140140; // 1 byte, not 0 if enabled
constexpr int overworldCustomMosaicArray = 0x1301F0;
// ============================================================================
// Dungeon Map Related Variables
// ============================================================================

View File

@@ -127,7 +127,7 @@ void Viewer::DrawViewMenu() {
if (show_memory_editor) {
static MemoryEditor mem_edit;
mem_edit.DrawWindow("Memory Editor", (void*)&rom_, rom_.GetSize());
mem_edit.DrawWindow("Memory Editor", (void*)&rom_, rom_.size());
}
if (show_imgui_demo) {

View File

@@ -138,7 +138,7 @@ void MasterEditor::DrawInfoPopup() {
if (ImGui::BeginPopupModal("ROM Information", nullptr,
ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("Title: %s", rom_.GetTitle());
ImGui::Text("ROM Size: %ld", rom_.GetSize());
ImGui::Text("ROM Size: %ld", rom_.size());
if (ImGui::Button("Close", ImVec2(200, 0))) {
rom_info_ = false;
@@ -216,7 +216,7 @@ void MasterEditor::DrawViewMenu() {
if (show_memory_editor) {
static MemoryEditor mem_edit;
mem_edit.DrawWindow("Memory Editor", (void *)&rom_, rom_.GetSize());
mem_edit.DrawWindow("Memory Editor", (void *)&rom_, rom_.size());
}
if (show_imgui_demo) {

View File

@@ -107,7 +107,7 @@ absl::Status OverworldEditor::DrawToolset() {
BUTTON_COLUMN(ICON_MD_ZOOM_OUT) // Zoom Out
BUTTON_COLUMN(ICON_MD_ZOOM_IN) // Zoom In
TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
BUTTON_COLUMN(ICON_MD_DRAW); // Draw Tile
BUTTON_COLUMN(ICON_MD_DRAW) // Draw Tile
BUTTON_COLUMN(ICON_MD_DOOR_FRONT) // Entrances
BUTTON_COLUMN(ICON_MD_DOOR_BACK) // Exits
BUTTON_COLUMN(ICON_MD_GRASS) // Items

View File

@@ -17,6 +17,7 @@
#include "app/gfx/bitmap.h"
#include "app/gfx/snes_tile.h"
#include "gui/canvas.h"
#include "gui/icons.h"
#include "gui/input.h"
namespace yaze {
@@ -63,37 +64,40 @@ void ScreenEditor::DrawInventoryMenuEditor() {
TAB_ITEM("Inventory Menu")
static bool create = false;
if (!create) {
PRINT_IF_ERROR(rom_.LoadAllGraphicsData())
all_gfx_ = rom_.GetGraphicsBuffer();
inventory_.Create(all_gfx_);
if (!create && rom_.isLoaded()) {
inventory_.Create();
palette_ =inventory_.Palette();
create = true;
}
if (ImGui::BeginTable("InventoryScreen", 2, ImGuiTableFlags_Resizable)) {
DrawInventoryToolset();
if (ImGui::BeginTable("InventoryScreen", 3, ImGuiTableFlags_Resizable)) {
ImGui::TableSetupColumn("Canvas");
ImGui::TableSetupColumn("Tiles");
ImGui::TableSetupColumn("Palette");
ImGui::TableHeadersRow();
ImGui::TableNextColumn();
screen_canvas_.DrawBackground();
screen_canvas_.DrawContextMenu();
screen_canvas_.DrawBitmap(inventory_.Bitmap(), 2, create);
screen_canvas_.DrawGrid();
screen_canvas_.DrawGrid(32.0f);
screen_canvas_.DrawOverlay();
ImGui::TableNextColumn();
tilesheet_canvas_.DrawBackground(ImVec2(128 * 2 + 2, 192 * 2 + 2));
tilesheet_canvas_.DrawBackground(ImVec2(128 * 2 + 2, (192 * 2) + 4));
tilesheet_canvas_.DrawContextMenu();
tilesheet_canvas_.DrawBitmap(inventory_.Tilesheet(), 2, create);
tilesheet_canvas_.DrawGrid(16.0f);
tilesheet_canvas_.DrawOverlay();
ImGui::TableNextColumn();
gui::DisplayPalette(palette_, create);
ImGui::EndTable();
}
ImGui::SameLine();
ImGui::Separator();
END_TAB_ITEM()
}
@@ -138,7 +142,7 @@ void ScreenEditor::DrawMosaicEditor() {
gui::InputHex("Routine Location", &overworldCustomMosaicASM);
if (ImGui::Button("Generate Mosaic Assembly")) {
auto mosaic = mosaic_script_.GenerateMosaicChangeAssembly(
auto mosaic = mosaic_script_.PatchOverworldMosaic(
rom_, mosaic_tiles_, overworldCustomMosaicASM);
if (!mosaic.ok()) {
std::cout << mosaic;
@@ -168,6 +172,30 @@ void ScreenEditor::DrawToolset() {
ImGui::Checkbox("Draw BG3", &drawing_bg3);
}
void ScreenEditor::DrawInventoryToolset() {
if (ImGui::BeginTable("InventoryToolset", 8, ImGuiTableFlags_SizingFixedFit, ImVec2(0, 0))) {
ImGui::TableSetupColumn("#drawTool");
ImGui::TableSetupColumn("#sep1");
ImGui::TableSetupColumn("#zoomOut");
ImGui::TableSetupColumn("#zoomIN");
ImGui::TableSetupColumn("#sep2");
ImGui::TableSetupColumn("#bg2Tool");
ImGui::TableSetupColumn("#bg3Tool");
ImGui::TableSetupColumn("#itemTool");
BUTTON_COLUMN(ICON_MD_UNDO)
BUTTON_COLUMN(ICON_MD_REDO)
TEXT_COLUMN(ICON_MD_MORE_VERT)
BUTTON_COLUMN(ICON_MD_ZOOM_OUT)
BUTTON_COLUMN(ICON_MD_ZOOM_IN)
TEXT_COLUMN(ICON_MD_MORE_VERT)
BUTTON_COLUMN(ICON_MD_DRAW)
BUTTON_COLUMN(ICON_MD_BUILD)
ImGui::EndTable();
}
}
} // namespace editor
} // namespace app
} // namespace yaze

View File

@@ -9,9 +9,12 @@
#include "app/core/constants.h"
#include "app/gfx/bitmap.h"
#include "app/gfx/snes_tile.h"
#include "app/gfx/snes_palette.h"
#include "app/rom.h"
#include "app/zelda3/inventory.h"
#include "gui/canvas.h"
#include "gui/icons.h"
#include "gui/color.h"
namespace yaze {
namespace app {
@@ -19,7 +22,6 @@ namespace editor {
using MosaicArray = std::array<int, core::kNumOverworldMaps>;
static int overworldCustomMosaicASM = 0x1301D0;
static int overworldCustomMosaicArray = 0x1301F0;
class ScreenEditor {
public:
@@ -39,6 +41,7 @@ class ScreenEditor {
void DrawInventoryMenuEditor();
void DrawToolset();
void DrawInventoryToolset();
void DrawWorldGrid(int world, int h = 8, int w = 8);
char mosaic_tiles_[core::kNumOverworldMaps];
@@ -46,6 +49,7 @@ class ScreenEditor {
ROM rom_;
Bytes all_gfx_;
zelda3::Inventory inventory_;
gfx::SNESPalette palette_;
snes_asm::Script mosaic_script_;
gui::Canvas screen_canvas_;
gui::Canvas tilesheet_canvas_;

View File

@@ -302,7 +302,7 @@ absl::Status ValidateCompressionResult(
RETURN_IF_ERROR(temp_rom.LoadFromBytes(
CreateCompressionString(compressed_chain_start->next, mode)))
ASSIGN_OR_RETURN(auto decomp_data,
temp_rom.Decompress(0, temp_rom.GetSize()))
temp_rom.Decompress(0, temp_rom.size()))
if (!std::equal(decomp_data.begin() + start, decomp_data.end(),
temp_rom.begin())) {
return absl::InternalError(absl::StrFormat(
@@ -352,7 +352,7 @@ int GetGraphicsAddress(const uchar* data, uint8_t offset) {
return core::SnesToPc(snes_addr);
}
Bytes SNES3bppTo8bppSheet(Bytes sheet, int bpp) {
Bytes SnesTo8bppSheet(Bytes sheet, int bpp) {
int xx = 0; // positions where we are at on the sheet
int yy = 0;
int pos = 0;
@@ -368,12 +368,9 @@ Bytes SNES3bppTo8bppSheet(Bytes sheet, int bpp) {
}
Bytes sheet_buffer_out(buffer_size);
// for each tiles, 16 per line
for (int i = 0; i < num_tiles; i++) {
// for each line
for (int y = 0; y < 8; y++) {
//[0] + [1] + [16]
for (int x = 0; x < 8; x++) {
for (int i = 0; i < num_tiles; i++) { // for each tiles, 16 per line
for (int y = 0; y < 8; y++) { // for each line
for (int x = 0; x < 8; x++) { //[0] + [1] + [16]
auto b1 = ((sheet[(y * 2) + (bpp * pos)] & (kGraphicsBitmap[x])));
auto b2 = (sheet[((y * 2) + (bpp * pos)) + 1] & (kGraphicsBitmap[x]));
auto b3 = (sheet[(16 + y) + (bpp * pos)] & (kGraphicsBitmap[x]));
@@ -457,7 +454,6 @@ absl::StatusOr<Bytes> ROM::Compress(const int start, const int length, int mode,
comp_accumulator = 0;
}
} else {
// Anything is better than directly copying bytes...
lc_lz2::CompressionCommandAlternative(
rom_data_.data(), compressed_chain, cmd_size, cmd_args, src_data_pos,
comp_accumulator, cmd_with_max, max_win);
@@ -474,8 +470,8 @@ absl::StatusOr<Bytes> ROM::Compress(const int start, const int length, int mode,
}
}
lc_lz2::MergeCopy(
compressed_chain_start->next); // Skipping compression chain header
// Skipping compression chain header
lc_lz2::MergeCopy(compressed_chain_start->next);
lc_lz2::PrintCompressionChain(compressed_chain_start);
return lc_lz2::CreateCompressionString(compressed_chain_start->next, mode);
}
@@ -515,10 +511,8 @@ absl::StatusOr<Bytes> ROM::Decompress(int offset, int size, int mode) {
offset += length;
break;
case kCommandByteFill:
for (int i = 0; i < length; i++) {
buffer[buffer_pos] = rom_data_[offset];
buffer_pos++;
}
memset(buffer.data() + buffer_pos, (int)(rom_data_[offset]), length);
buffer_pos += length;
offset += 1; // Advances 1 byte in the ROM
break;
case kCommandWordFill: {
@@ -543,35 +537,23 @@ absl::StatusOr<Bytes> ROM::Decompress(int offset, int size, int mode) {
ushort s1 = ((rom_data_[offset + 1] & kSnesByteMax) << 8);
ushort s2 = ((rom_data_[offset] & kSnesByteMax));
int addr = (s1 | s2);
if (mode == kNintendoMode1) { // Reversed byte order for overworld maps
// addr = (s2 | s1);
addr = (rom_data_[offset + 1] & kSnesByteMax) |
((rom_data_[offset] & kSnesByteMax) << 8);
if (addr > offset) {
return absl::InternalError(absl::StrFormat(
"Decompress: Offset for command copy exceeds current position "
"(Offset : %#04x | Pos : %#06x)\n",
addr, offset));
}
if (buffer_pos + length >= size) {
size *= 2;
buffer.resize(size);
}
memcpy(buffer.data() + buffer_pos, buffer.data() + addr, length);
buffer_pos += length;
offset += 2;
break;
}
for (int i = 0; i < length; i++) {
buffer[buffer_pos] = buffer[addr + i];
buffer_pos++;
if (addr > offset) {
return absl::InternalError(absl::StrFormat(
"Decompress: Offset for command copy exceeds current position "
"(Offset : %#04x | Pos : %#06x)\n",
addr, offset));
}
offset += 2; // Advance 2 bytes in the ROM
if (buffer_pos + length >= size) {
size *= 2;
buffer.resize(size);
}
memcpy(buffer.data() + buffer_pos, buffer.data() + addr, length);
buffer_pos += length;
offset += 2;
} break;
default: {
std::cout << absl::StrFormat(
@@ -598,12 +580,12 @@ absl::StatusOr<Bytes> ROM::Load2bppGraphics() {
Bytes sheet;
const uint8_t sheets[] = {113, 114, 218, 219, 220, 221};
for (int i = 0; i < 6; i++) {
auto offset = GetGraphicsAddress(rom_data_.data(), sheets[i]);
for (const auto& sheet_id : sheets) {
auto offset = GetGraphicsAddress(rom_data_.data(), sheet_id);
ASSIGN_OR_RETURN(auto decomp_sheet, Decompress(offset))
auto converted_sheet = SNES3bppTo8bppSheet(decomp_sheet, 2);
for (int j = 0; j < converted_sheet.size(); ++j) {
sheet.push_back(converted_sheet.at(j));
auto converted_sheet = SnesTo8bppSheet(decomp_sheet, 2);
for (const auto& each_pixel : converted_sheet) {
sheet.push_back(each_pixel);
}
}
return sheet;
@@ -627,8 +609,6 @@ absl::Status ROM::LoadAllGraphicsData() {
}
bpp3 = true;
} else if (i == 113 || i == 114 || i >= 218) {
// auto offset = GetGraphicsAddress(rom_data_.data(), i);
// ASSIGN_OR_RETURN(sheet, Decompress(offset))
bpp3 = false;
} else {
auto offset = GetGraphicsAddress(rom_data_.data(), i);
@@ -637,7 +617,7 @@ absl::Status ROM::LoadAllGraphicsData() {
}
if (bpp3) {
auto converted_sheet = SNES3bppTo8bppSheet(sheet, 3);
auto converted_sheet = SnesTo8bppSheet(sheet, 3);
graphics_bin_[i] =
gfx::Bitmap(core::kTilesheetWidth, core::kTilesheetHeight,
core::kTilesheetDepth, converted_sheet.data(), 0x1000);
@@ -647,15 +627,8 @@ absl::Status ROM::LoadAllGraphicsData() {
graphics_buffer_.push_back(graphics_bin_.at(i).GetByte(j));
}
} else {
// auto converted_sheet = SNES3bppTo8bppSheet(sheet, 2);
// graphics_bin_[i] =
// gfx::Bitmap(core::kTilesheetWidth, core::kTilesheetHeight,
// core::kTilesheetDepth, converted_sheet.data(), 0x1000);
// graphics_bin_.at(i).CreateTexture(renderer_);
for (int j = 0; j < graphics_bin_.at(0).GetSize(); ++j) {
graphics_buffer_.push_back(0xFF);
// graphics_buffer_.push_back(graphics_bin_.at(i).GetByte(j));
}
}
}

View File

@@ -93,7 +93,6 @@ class ROM {
void RenderBitmap(gfx::Bitmap* bitmap) const;
auto GetSize() const { return size_; }
auto GetTitle() const { return title; }
auto GetGraphicsBin() const { return graphics_bin_; }
auto GetGraphicsBuffer() const { return graphics_buffer_; }
@@ -105,6 +104,7 @@ class ROM {
auto begin() { return rom_data_.begin(); }
auto end() { return rom_data_.end(); }
auto data() { return rom_data_.data(); }
auto size() const { return size_; }
uchar& operator[](int i) {
if (i > size_) {

View File

@@ -8,22 +8,18 @@
namespace yaze {
namespace app {
namespace zelda3 {
void Inventory::Create(Bytes& all_gfx) {
void Inventory::Create() {
data_.reserve(256 * 256);
for (int i = 0; i < 256 * 256; i++) {
data_.push_back(0xFF);
}
PRINT_IF_ERROR(BuildTileset(all_gfx))
//tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(kInventoryStart)));
tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(kBowItemPos)));
tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(kBowItemPos + 0x02)));
tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(kBowItemPos + 0x04)));
tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(kBowItemPos + 0x08)));
// tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(kLampItemPos)));
// tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(kLampItemPos + 0x02)));
// tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(kLampItemPos + 0x04)));
// tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(kLampItemPos + 0x08)));
PRINT_IF_ERROR(BuildTileset())
for (int i = 0; i < 0x400; i += 0x08) {
tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(i + kBowItemPos)));
tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(i + kBowItemPos + 0x02)));
tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(i + kBowItemPos + 0x04)));
tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(i + kBowItemPos + 0x08)));
}
const int offsets[] = {0x00, 0x08, 0x800, 0x808};
auto xx = 0;
auto yy = 0;
@@ -49,15 +45,15 @@ void Inventory::Create(Bytes& all_gfx) {
int source = ypos + xpos + (x + (y * 0x80));
auto destination = xx + yy + offset + (mx + (my * 0x100));
data_[destination] = (tilesheets_[source] & 0x0F);
data_[destination] = (test_[source] & 0x0F) + tile.palette_ * 0x08;
}
}
if (i == 4) {
i = 0;
xx += 0x10;
if (xx >= 0x80) {
yy += 0x800;
if (xx >= 0x100) {
yy += 0x1000;
xx = 0;
}
} else {
@@ -65,15 +61,24 @@ void Inventory::Create(Bytes& all_gfx) {
}
}
bitmap_.Create(256, 256, 128, data_);
// bitmap_.ApplyPalette(rom_.GetPaletteGroup("hud")[0]);
bitmap_.ApplyPalette(palette_);
rom_.RenderBitmap(&bitmap_);
}
absl::Status Inventory::BuildTileset(Bytes& all_gfx) {
absl::Status Inventory::BuildTileset() {
tilesheets_.reserve(6 * 0x2000);
for (int i = 0; i < 6 * 0x2000; i++) tilesheets_.push_back(0xFF);
ASSIGN_OR_RETURN(tilesheets_, rom_.Load2bppGraphics())
tilesheets_bmp_.Create(128, 192 + 96 + 48 - 16, 64, tilesheets_);
Bytes test;
for (int i = 0; i < 0x4000; i++) {
test_.push_back(tilesheets_[i]);
}
for (int i = 0x8000; i < + 0x8000 + 0x2000; i++) {
test_.push_back(tilesheets_[i]);
}
tilesheets_bmp_.Create(128, 0x130, 64, test_);
palette_ = rom_.GetPaletteGroup("hud")[0];
tilesheets_bmp_.ApplyPalette(palette_);
rom_.RenderBitmap(&tilesheets_bmp_);
return absl::OkStatus();
}

View File

@@ -3,6 +3,7 @@
#include "app/gfx/bitmap.h"
#include "app/gfx/snes_tile.h"
#include "app/gfx/snes_palette.h"
#include "app/rom.h"
#include "gui/canvas.h"
@@ -11,7 +12,6 @@ namespace app {
namespace zelda3 {
constexpr int kInventoryStart = 0x6564A;
constexpr int kLampItemPos = 0x6F6F9;
constexpr int kBowItemPos = 0x6F631;
class Inventory {
@@ -19,11 +19,12 @@ class Inventory {
void SetupROM(ROM& rom) { rom_ = rom; }
auto Bitmap() const { return bitmap_; }
auto Tilesheet() const { return tilesheets_bmp_; }
auto Palette() const { return palette_; }
void Create(Bytes& all_gfx);
void Create();
private:
absl::Status BuildTileset(Bytes& all_gfx);
absl::Status BuildTileset();
ROM rom_;
@@ -31,7 +32,9 @@ class Inventory {
gfx::Bitmap bitmap_;
Bytes tilesheets_;
Bytes test_;
gfx::Bitmap tilesheets_bmp_;
gfx::SNESPalette palette_;
gui::Canvas canvas_;
std::vector<gfx::TileInfo> tiles_;

View File

@@ -64,6 +64,7 @@ void Canvas::DrawContextMenu() {
ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight);
if (ImGui::BeginPopup("context")) {
ImGui::MenuItem("Show Grid", nullptr, &enable_grid_);
if (ImGui::MenuItem("Reset Position", nullptr, false)) {
scrolling_.x = 0;
scrolling_.y = 0;

84
src/gui/color.cc Normal file
View File

@@ -0,0 +1,84 @@
#include "color.h"
#include <imgui/imgui.h>
#include <cmath>
#include <string>
#include "app/gfx/bitmap.h"
#include "app/gfx/snes_palette.h"
namespace yaze {
namespace gui {
void DisplayPalette(app::gfx::SNESPalette& palette, bool loaded) {
static ImVec4 color = ImVec4(0, 0, 0, 255.f);
ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview |
ImGuiColorEditFlags_NoDragDrop |
ImGuiColorEditFlags_NoOptions;
// Generate a default palette. The palette will persist and can be edited.
static bool init = false;
static ImVec4 saved_palette[32] = {};
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
}
init = true;
}
static ImVec4 backup_color;
ImGui::Text("Current ==>");
ImGui::SameLine();
ImGui::Text("Previous");
ImGui::ColorButton(
"##current", color,
ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
ImVec2(60, 40));
ImGui::SameLine();
if (ImGui::ColorButton(
"##previous", backup_color,
ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
ImVec2(60, 40)))
color = backup_color;
ImGui::Separator();
ImGui::BeginGroup(); // Lock X position
ImGui::Text("Palette");
for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) {
ImGui::PushID(n);
if ((n % 4) != 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::BeginDragDropTarget()) {
if (const ImGuiPayload* payload =
ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
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);
ImGui::EndDragDropTarget();
}
ImGui::PopID();
}
ImGui::EndGroup();
ImGui::SameLine();
ImGui::ColorPicker4("##picker", (float*)&color,
misc_flags | ImGuiColorEditFlags_NoSidePreview |
ImGuiColorEditFlags_NoSmallPreview);
}
} // namespace gui
} // namespace yaze

20
src/gui/color.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef YAZE_GUI_COLOR_H
#define YAZE_GUI_COLOR_H
#include <imgui/imgui.h>
#include <cmath>
#include <string>
#include "app/gfx/bitmap.h"
#include "app/gfx/snes_palette.h"
namespace yaze {
namespace gui {
void DisplayPalette(app::gfx::SNESPalette& palette, bool loaded);
} // namespace gui
} // namespace yaze
#endif

View File

@@ -30,7 +30,7 @@ using ::testing::Return;
class MockScript : public Script {
public:
MOCK_METHOD(absl::Status, ApplyPatchToROM, (ROM & rom));
MOCK_METHOD(absl::Status, GenerateMosaicChangeAssembly,
MOCK_METHOD(absl::Status, PatchOverworldMosaic,
(ROM & rom, char mosaic_tiles[yaze::app::core::kNumOverworldMaps],
int routine_offset, int hook_offset));
};
@@ -40,15 +40,15 @@ TEST(ASMTest, ApplyMosaicChangePatchOk) {
MockScript script;
char mosaic_tiles[yaze::app::core::kNumOverworldMaps];
EXPECT_CALL(script, GenerateMosaicChangeAssembly(_, Eq(mosaic_tiles),
Eq(0x1301D0 + 0x138000), 0))
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.GenerateMosaicChangeAssembly(rom, mosaic_tiles,
0x1301D0 + 0x138000, 0),
absl::OkStatus());
EXPECT_THAT(
script.PatchOverworldMosaic(rom, mosaic_tiles, 0x1301D0 + 0x138000, 0),
absl::OkStatus());
EXPECT_THAT(script.ApplyPatchToROM(rom), absl::OkStatus());
}