Popout PaletteEditor, general housekeeping

This commit is contained in:
scawful
2023-05-22 09:16:20 -05:00
parent 02b1adb6ab
commit 5ac7002c88
45 changed files with 254 additions and 334 deletions

View File

@@ -12,8 +12,8 @@
#include "absl/status/status.h"
#include "absl/strings/str_format.h"
#include "app/editor/master_editor.h"
#include "gui/icons.h"
#include "gui/style.h"
#include "app/gui/icons.h"
#include "app/gui/style.h"
namespace yaze {
namespace app {

View File

@@ -11,8 +11,8 @@
#include "absl/status/status.h"
#include "app/editor/master_editor.h"
#include "gui/icons.h"
#include "gui/style.h"
#include "app/gui/icons.h"
#include "app/gui/style.h"
int main(int argc, char **argv);

View File

@@ -1,7 +1,7 @@
#include "assembly_editor.h"
#include "core/constants.h"
#include "gui/widgets.h"
#include "app/gui/widgets.h"
namespace yaze {
namespace app {
@@ -12,8 +12,8 @@ AssemblyEditor::AssemblyEditor() {
text_editor_.SetPalette(TextEditor::GetDarkPalette());
}
void AssemblyEditor::Update() {
ImGui::Begin("Assembly Editor", &file_is_loaded_);
void AssemblyEditor::Update(bool &is_loaded) {
ImGui::Begin("Assembly Editor", &is_loaded);
MENU_BAR()
DrawFileMenu();
DrawEditMenu();

View File

@@ -16,7 +16,7 @@ class AssemblyEditor {
public:
AssemblyEditor();
void Update();
void Update(bool &is_loaded);
void InlineUpdate();
void ChangeActiveFile(const std::string &);

View File

@@ -1,6 +1,6 @@
#include "dungeon_editor.h"
#include "gui/icons.h"
#include "app/gui/icons.h"
namespace yaze {
namespace app {

View File

@@ -3,8 +3,8 @@
#include <imgui/imgui.h>
#include "gui/canvas.h"
#include "gui/icons.h"
#include "app/gui/canvas.h"
#include "app/gui/icons.h"
#include "rom.h"
#include "zelda3/dungeon/room.h"

View File

@@ -15,10 +15,10 @@
#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"
#include "gui/widgets.h"
#include "app/gui/canvas.h"
#include "app/gui/icons.h"
#include "app/gui/input.h"
#include "app/gui/widgets.h"
namespace yaze {
namespace app {
@@ -213,6 +213,7 @@ void MasterEditor::DrawViewMenu() {
static bool show_asm_editor = false;
static bool show_imgui_demo = false;
static bool show_memory_viewer = false;
static bool show_palette_editor = false;
if (show_imgui_metrics) {
ImGui::ShowMetricsWindow(&show_imgui_metrics);
@@ -228,7 +229,13 @@ void MasterEditor::DrawViewMenu() {
}
if (show_asm_editor) {
assembly_editor_.Update();
assembly_editor_.Update(show_asm_editor);
}
if (show_palette_editor) {
ImGui::Begin("Palette Editor", &show_palette_editor);
palette_editor_.Update();
ImGui::End();
}
if (show_imgui_style_editor) {
@@ -263,6 +270,7 @@ void MasterEditor::DrawViewMenu() {
if (ImGui::BeginMenu("View")) {
ImGui::MenuItem("HEX Editor", nullptr, &show_memory_editor);
ImGui::MenuItem("ASM Editor", nullptr, &show_asm_editor);
ImGui::MenuItem("Palette Editor", nullptr, &show_palette_editor);
ImGui::MenuItem("Memory Viewer", nullptr, &show_memory_viewer);
ImGui::MenuItem("ImGui Demo", nullptr, &show_imgui_demo);
ImGui::Separator();

View File

@@ -18,9 +18,9 @@
#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"
#include "app/gui/canvas.h"
#include "app/gui/icons.h"
#include "app/gui/input.h"
namespace yaze {
namespace app {

View File

@@ -5,9 +5,9 @@
#include "absl/strings/str_format.h"
#include "app/editor/assembly_editor.h"
#include "gui/canvas.h"
#include "gui/icons.h"
#include "gui/input.h"
#include "app/gui/canvas.h"
#include "app/gui/icons.h"
#include "app/gui/input.h"
#include "snes_spc/demo/demo_util.h"
#include "snes_spc/demo/wave_writer.h"
#include "snes_spc/snes_spc/spc.h"

View File

@@ -6,11 +6,11 @@
#include "absl/strings/str_format.h"
#include "app/editor/assembly_editor.h"
#include "app/gui/canvas.h"
#include "app/gui/icons.h"
#include "app/gui/input.h"
#include "app/rom.h"
#include "app/zelda3/tracker.h"
#include "gui/canvas.h"
#include "gui/icons.h"
#include "gui/input.h"
#include "app/zelda3/music/tracker.h"
#include "snes_spc/demo/demo_util.h"
#include "snes_spc/demo/wave_writer.h"
#include "snes_spc/snes_spc/spc.h"

View File

@@ -15,8 +15,8 @@
#include "app/gfx/snes_tile.h"
#include "app/rom.h"
#include "app/zelda3/overworld.h"
#include "gui/canvas.h"
#include "gui/icons.h"
#include "app/gui/canvas.h"
#include "app/gui/icons.h"
namespace yaze {
namespace app {
@@ -196,9 +196,8 @@ void OverworldEditor::DrawOverworldCanvas() {
if (!blockset_canvas_.Points().empty()) {
int x = blockset_canvas_.Points().front().x / 32;
int y = blockset_canvas_.Points().front().y / 32;
// std::cout << x << " " << y << std::endl;
current_tile16_ = x + (y * 8);
// std::cout << current_tile16_ << std::endl;
current_tile16_ = x + (y * 0x10);
if (ow_map_canvas_.DrawTilePainter(tile16_individual_[current_tile16_],
16)) {
// Update the overworld map.
@@ -326,12 +325,12 @@ absl::Status OverworldEditor::LoadGraphics() {
for (int i = 0; i < 4096; i++) {
// Create a new vector for the pixel data of the current tile
Bytes tile_data;
for (int j = 0; j < 32 * 32; j++) tile_data.push_back(0x00);
for (int j = 0; j < 16 * 16; j++) tile_data.push_back(0x00);
// Copy the pixel data for the current tile into the vector
for (int ty = 0; ty < 32; ty++) {
for (int tx = 0; tx < 32; tx++) {
int position = (tx + (ty * 0x20));
for (int ty = 0; ty < 16; ty++) {
for (int tx = 0; tx < 16; tx++) {
int position = (tx + (ty * 0x10));
uchar value = tile16_data[i + tx + (ty * 0x80)];
tile_data[position] = value;
}
@@ -343,8 +342,7 @@ absl::Status OverworldEditor::LoadGraphics() {
// Render the bitmaps of each tile.
for (int id = 0; id < 4096; id++) {
gfx::Bitmap new_tile16;
tile16_individual_.emplace_back(new_tile16);
tile16_individual_.emplace_back();
tile16_individual_[id].Create(0x10, 0x10, 0x80,
tile16_individual_data_[id]);
tile16_individual_[id].ApplyPalette(palette_);

View File

@@ -16,8 +16,8 @@
#include "app/gfx/snes_tile.h"
#include "app/rom.h"
#include "app/zelda3/overworld.h"
#include "gui/canvas.h"
#include "gui/icons.h"
#include "app/gui/canvas.h"
#include "app/gui/icons.h"
namespace yaze {
namespace app {

View File

@@ -4,8 +4,8 @@
#include "absl/status/status.h"
#include "app/gfx/snes_palette.h"
#include "gui/canvas.h"
#include "gui/icons.h"
#include "app/gui/canvas.h"
#include "app/gui/icons.h"
static inline float ImSaturate(float f) {
return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f;
@@ -41,17 +41,9 @@ using namespace ImGui;
} // 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];
@@ -106,8 +98,6 @@ void PaletteEditor::DrawPaletteGroup(int i) {
ImGui::PopID();
}
}
ImGui::EndTable();
}
absl::Status PaletteEditor::Update() {
@@ -159,6 +149,10 @@ void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) {
ImGui::SameLine();
ImGui::Text("Previous");
if (ImGui::Button("Update Map Palette")) {
}
ImGui::ColorButton(
"##current", color,
ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
@@ -170,6 +164,8 @@ void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) {
ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
ImVec2(60, 40)))
color = backup_color;
// List of Colors in Overworld Palette
ImGui::Separator();
ImGui::Text("Palette");
for (int n = 0; n < IM_ARRAYSIZE(saved_palette_); n++) {

View File

@@ -6,8 +6,8 @@
#include "absl/status/status.h"
#include "app/gfx/snes_palette.h"
#include "app/rom.h"
#include "gui/canvas.h"
#include "gui/icons.h"
#include "app/gui/canvas.h"
#include "app/gui/icons.h"
namespace yaze {
namespace app {

View File

@@ -15,9 +15,9 @@
#include "app/core/constants.h"
#include "app/gfx/bitmap.h"
#include "app/gfx/snes_tile.h"
#include "gui/canvas.h"
#include "gui/icons.h"
#include "gui/input.h"
#include "app/gui/canvas.h"
#include "app/gui/icons.h"
#include "app/gui/input.h"
namespace yaze {
namespace app {

View File

@@ -9,11 +9,11 @@
#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/color.h"
#include "app/gui/icons.h"
#include "app/rom.h"
#include "app/zelda3/inventory.h"
#include "gui/canvas.h"
#include "gui/color.h"
#include "gui/icons.h"
#include "app/zelda3/screen/inventory.h"
namespace yaze {
namespace app {

View File

@@ -34,8 +34,23 @@ class TileInfo {
vertical_mirror_(v),
horizontal_mirror_(h),
palette_(palette) {}
// TODO(scawful): This is not the actual value yet.
ushort ToShort() const { return id_; }
ushort ToShort() const {
ushort result = 0;
// Copy the id_ value
result |= id_ & 0x3FF; // ids are 10 bits
// Set the vertical_mirror_, horizontal_mirror_, and over_ flags
result |= (vertical_mirror_ ? 1 : 0) << 10;
result |= (horizontal_mirror_ ? 1 : 0) << 11;
result |= (over_ ? 1 : 0) << 12;
// Set the palette_
result |= (palette_ & 0x07) << 13; // palettes are 3 bits
return result;
}
};
TileInfo GetTilesInfo(ushort tile);

222
src/app/gui/canvas.cc Normal file
View File

@@ -0,0 +1,222 @@
#include "canvas.h"
#include <imgui/imgui.h>
#include <cmath>
#include <string>
#include "app/gfx/bitmap.h"
#include "app/rom.h"
namespace yaze {
namespace gui {
// Background for the Canvas represents region without any content drawn to it,
// but can be controlled by the user.
void Canvas::DrawBackground(ImVec2 canvas_size) {
canvas_p0_ = ImGui::GetCursorScreenPos();
if (!custom_canvas_size_) canvas_sz_ = ImGui::GetContentRegionAvail();
if (canvas_size.x != 0) canvas_sz_ = canvas_size;
canvas_p1_ = ImVec2(canvas_p0_.x + canvas_sz_.x, canvas_p0_.y + canvas_sz_.y);
draw_list_ = ImGui::GetWindowDrawList(); // Draw border and background color
draw_list_->AddRectFilled(canvas_p0_, canvas_p1_, IM_COL32(32, 32, 32, 255));
draw_list_->AddRect(canvas_p0_, canvas_p1_, IM_COL32(255, 255, 255, 255));
}
// Context Menu refers to what happens when the right mouse button is pressed
// This routine also handles the scrolling for the canvas.
void Canvas::DrawContextMenu() {
// This will catch our interactions
const ImGuiIO &io = ImGui::GetIO();
ImGui::InvisibleButton(
"canvas", canvas_sz_,
ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
const bool is_active = ImGui::IsItemActive(); // Held
const ImVec2 origin(canvas_p0_.x + scrolling_.x,
canvas_p0_.y + scrolling_.y); // Lock scrolled origin
const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x,
io.MousePos.y - origin.y);
// Pan (we use a zero mouse threshold when there's no context menu)
if (const float mouse_threshold_for_pan = enable_context_menu_ ? -1.0f : 0.0f;
is_active &&
ImGui::IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan)) {
scrolling_.x += io.MouseDelta.x;
scrolling_.y += io.MouseDelta.y;
}
// Context menu (under default mouse threshold)
if (ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
enable_context_menu_ && drag_delta.x == 0.0f && drag_delta.y == 0.0f)
ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight);
// Contents of the Context Menu
if (ImGui::BeginPopup("context")) {
ImGui::MenuItem("Show Grid", nullptr, &enable_grid_);
if (ImGui::MenuItem("Reset Position", nullptr, false)) {
scrolling_.x = 0;
scrolling_.y = 0;
}
if (ImGui::MenuItem("Remove all", nullptr, false, points_.Size > 0)) {
points_.clear();
}
ImGui::EndPopup();
}
}
// Tile painter shows a preview of the currently selected tile
// and allows the user to left click to paint the tile or right
// click to select a new tile to paint with.
bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size) {
const ImGuiIO &io = ImGui::GetIO();
const bool is_hovered = ImGui::IsItemHovered(); // Hovered
const ImVec2 origin(canvas_p0_.x + scrolling_.x,
canvas_p0_.y + scrolling_.y); // Lock scrolled origin
const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x,
io.MousePos.y - origin.y);
if (is_hovered) {
// Reset the previous tile hover
if (!points_.empty()) {
points_.clear();
}
// Calculate the coordinates of the mouse
ImVec2 draw_tile_outline_pos;
draw_tile_outline_pos.x =
std::floor((double)mouse_pos_in_canvas.x / size) * size;
draw_tile_outline_pos.y =
std::floor((double)mouse_pos_in_canvas.y / size) * size;
auto draw_tile_outline_pos_end =
ImVec2(draw_tile_outline_pos.x + size, draw_tile_outline_pos.y + size);
points_.push_back(draw_tile_outline_pos);
points_.push_back(draw_tile_outline_pos_end);
if (bitmap.IsActive()) {
draw_list_->AddImage(
(void *)bitmap.GetTexture(),
ImVec2(origin.x + draw_tile_outline_pos.x,
origin.y + draw_tile_outline_pos.y),
ImVec2(origin.x + draw_tile_outline_pos.x + bitmap.GetWidth(),
origin.y + draw_tile_outline_pos.y + bitmap.GetHeight()));
}
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
// Draw the currently selected tile on the overworld here
// Save the coordinates of the selected tile.
drawn_tile_pos_ = mouse_pos_in_canvas;
return true;
}
} else {
// Erase the hover when the mouse is not in the canvas window.
points_.clear();
}
return false;
}
// Dictates which tile is currently selected based on what the user clicks
// in the canvas window. Represented and split apart into a grid of tiles.
void Canvas::DrawTileSelector(int size) {
const ImGuiIO &io = ImGui::GetIO();
const bool is_hovered = ImGui::IsItemHovered(); // Hovered
const ImVec2 origin(canvas_p0_.x + scrolling_.x,
canvas_p0_.y + scrolling_.y); // Lock scrolled origin
const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x,
io.MousePos.y - origin.y);
if (is_hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
if (!points_.empty()) {
points_.clear();
}
ImVec2 draw_tile_outline_pos;
draw_tile_outline_pos.x =
std::floor((double)mouse_pos_in_canvas.x / size) * size;
draw_tile_outline_pos.y =
std::floor((double)mouse_pos_in_canvas.y / size) * size;
points_.push_back(draw_tile_outline_pos);
points_.push_back(
ImVec2(draw_tile_outline_pos.x + size, draw_tile_outline_pos.y + size));
}
}
// Draws the contents of the Bitmap image to the Canvas
void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset, bool ready) {
if (ready) {
draw_list_->AddImage(
(void *)bitmap.GetTexture(),
ImVec2(canvas_p0_.x + border_offset, canvas_p0_.y + border_offset),
ImVec2(canvas_p0_.x + (bitmap.GetWidth() * 2),
canvas_p0_.y + (bitmap.GetHeight() * 2)));
}
}
void Canvas::DrawBitmap(const Bitmap &bitmap, int x_offset, int y_offset) {
draw_list_->AddImage(
(void *)bitmap.GetTexture(),
ImVec2(canvas_p0_.x + x_offset + scrolling_.x,
canvas_p0_.y + y_offset + scrolling_.y),
ImVec2(canvas_p0_.x + x_offset + scrolling_.x + (bitmap.GetWidth()),
canvas_p0_.y + y_offset + scrolling_.y + (bitmap.GetHeight())));
}
void Canvas::DrawOutline(int x, int y, int w, int h) {
ImVec2 origin(canvas_p0_.x + scrolling_.x + x,
canvas_p0_.y + scrolling_.y + y);
ImVec2 size(canvas_p0_.x + scrolling_.x + x + w,
canvas_p0_.y + scrolling_.y + y + h);
draw_list_->AddRect(origin, size, IM_COL32(255, 255, 255, 255));
}
// Canvas Wrapper for a Rectangle
void Canvas::DrawRect(int x, int y, int w, int h, ImVec4 color) {
ImVec2 origin(canvas_p0_.x + scrolling_.x + x,
canvas_p0_.y + scrolling_.y + y);
ImVec2 size(canvas_p0_.x + scrolling_.x + x + w,
canvas_p0_.y + scrolling_.y + y + h);
draw_list_->AddRectFilled(origin, size,
IM_COL32(color.x, color.y, color.z, color.w));
}
// Canvas Wrapper for Text
void Canvas::DrawText(std::string text, int x, int y) {
draw_list_->AddText(
ImVec2(canvas_p0_.x + scrolling_.x + x, canvas_p0_.y + scrolling_.y + y),
IM_COL32(255, 255, 255, 255), text.data());
}
void Canvas::DrawGrid(float grid_step) {
// Draw grid + all lines in the canvas
draw_list_->PushClipRect(canvas_p0_, canvas_p1_, true);
if (enable_grid_) {
for (float x = fmodf(scrolling_.x, grid_step); x < canvas_sz_.x;
x += grid_step)
draw_list_->AddLine(ImVec2(canvas_p0_.x + x, canvas_p0_.y),
ImVec2(canvas_p0_.x + x, canvas_p1_.y),
IM_COL32(200, 200, 200, 40));
for (float y = fmodf(scrolling_.y, grid_step); y < canvas_sz_.y;
y += grid_step)
draw_list_->AddLine(ImVec2(canvas_p0_.x, canvas_p0_.y + y),
ImVec2(canvas_p1_.x, canvas_p0_.y + y),
IM_COL32(200, 200, 200, 40));
}
}
void Canvas::DrawOverlay() {
const ImVec2 origin(canvas_p0_.x + scrolling_.x,
canvas_p0_.y + scrolling_.y); // Lock scrolled origin
for (int n = 0; n < points_.Size; n += 2) {
draw_list_->AddRect(
ImVec2(origin.x + points_[n].x, origin.y + points_[n].y),
ImVec2(origin.x + points_[n + 1].x, origin.y + points_[n + 1].y),
IM_COL32(255, 255, 255, 255), 1.0f);
}
draw_list_->PopClipRect();
}
} // namespace gui
} // namespace yaze

72
src/app/gui/canvas.h Normal file
View File

@@ -0,0 +1,72 @@
#ifndef YAZE_GUI_CANVAS_H
#define YAZE_GUI_CANVAS_H
#include <imgui/imgui.h>
#include <cmath>
#include <string>
#include "app/gfx/bitmap.h"
#include "app/rom.h"
namespace yaze {
namespace gui {
using app::gfx::Bitmap;
class Canvas {
public:
Canvas() = default;
explicit Canvas(ImVec2 canvas_size)
: custom_canvas_size_(true), canvas_sz_(canvas_size) {}
void DrawBackground(ImVec2 canvas_size = ImVec2(0, 0));
void DrawContextMenu();
bool DrawTilePainter(const Bitmap& bitmap, int size);
void DrawTileSelector(int size);
void DrawBitmap(const Bitmap& bitmap, int border_offset = 0,
bool ready = true);
void DrawBitmap(const Bitmap& bitmap, int x_offset, int y_offset);
void DrawOutline(int x, int y, int w, int h);
void DrawRect(int x, int y, int w, int h, ImVec4 color);
void DrawText(std::string text, int x, int y);
void DrawGrid(float grid_step = 64.0f);
void DrawOverlay(); // last
auto Points() const { return points_; }
auto GetDrawList() const { return draw_list_; }
auto GetZeroPoint() const { return canvas_p0_; }
auto GetCurrentDrawnTilePosition() const { return drawn_tile_pos_; }
auto GetCanvasSize() const { return canvas_sz_; }
void SetCanvasSize(ImVec2 canvas_size) {
canvas_sz_ = canvas_size;
custom_canvas_size_ = true;
}
private:
bool enable_grid_ = true;
bool enable_context_menu_ = true;
bool custom_canvas_size_ = false;
bool is_hovered_ = false;
ImDrawList* draw_list_;
ImVector<ImVec2> points_;
ImVec2 scrolling_;
ImVec2 canvas_sz_;
ImVec2 canvas_p0_;
ImVec2 canvas_p1_;
ImVec2 mouse_pos_in_canvas_;
ImVec2 drawn_tile_pos_;
std::vector<app::gfx::Bitmap> changed_tiles_;
app::gfx::Bitmap current_tile_;
std::string title_;
};
} // namespace gui
} // namespace yaze
#endif

84
src/app/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/app/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

2192
src/app/gui/icons.h Normal file

File diff suppressed because it is too large Load Diff

70
src/app/gui/input.cc Normal file
View File

@@ -0,0 +1,70 @@
#include "input.h"
#include <imgui/imgui.h>
#include <imgui/imgui_internal.h>
#include "absl/strings/string_view.h"
namespace yaze {
namespace gui {
const int kStepOneHex = 0x01;
const int kStepFastHex = 0x0F;
bool InputHex(const char* label, int* data) {
return ImGui::InputScalar(label, ImGuiDataType_U64, data, &kStepOneHex,
&kStepFastHex, "%06X",
ImGuiInputTextFlags_CharsHexadecimal);
}
bool InputHexShort(const char* label, int* data) {
return ImGui::InputScalar(label, ImGuiDataType_U32, data, &kStepOneHex,
&kStepFastHex, "%06X",
ImGuiInputTextFlags_CharsHexadecimal);
}
void ItemLabel(absl::string_view title, ItemLabelFlags flags) {
ImGuiWindow* window = ImGui::GetCurrentWindow();
const ImVec2 lineStart = ImGui::GetCursorScreenPos();
const ImGuiStyle& style = ImGui::GetStyle();
float fullWidth = ImGui::GetContentRegionAvail().x;
float itemWidth = ImGui::CalcItemWidth() + style.ItemSpacing.x;
ImVec2 textSize = ImGui::CalcTextSize(title.begin(), title.end());
ImRect textRect;
textRect.Min = ImGui::GetCursorScreenPos();
if (flags & ItemLabelFlag::Right) textRect.Min.x = textRect.Min.x + itemWidth;
textRect.Max = textRect.Min;
textRect.Max.x += fullWidth - itemWidth;
textRect.Max.y += textSize.y;
ImGui::SetCursorScreenPos(textRect.Min);
ImGui::AlignTextToFramePadding();
// Adjust text rect manually because we render it directly into a drawlist
// instead of using public functions.
textRect.Min.y += window->DC.CurrLineTextBaseOffset;
textRect.Max.y += window->DC.CurrLineTextBaseOffset;
ImGui::ItemSize(textRect);
if (ImGui::ItemAdd(
textRect, window->GetID(title.data(), title.data() + title.size()))) {
ImGui::RenderTextEllipsis(
ImGui::GetWindowDrawList(), textRect.Min, textRect.Max, textRect.Max.x,
textRect.Max.x, title.data(), title.data() + title.size(), &textSize);
if (textRect.GetWidth() < textSize.x && ImGui::IsItemHovered())
ImGui::SetTooltip("%.*s", (int)title.size(), title.data());
}
if (flags & ItemLabelFlag::Left) {
ImVec2 result;
auto other = ImVec2{0, textSize.y + window->DC.CurrLineTextBaseOffset};
result.x = textRect.Max.x - other.x;
result.y = textRect.Max.y - other.y;
ImGui::SetCursorScreenPos(result);
ImGui::SameLine();
} else if (flags & ItemLabelFlag::Right)
ImGui::SetCursorScreenPos(lineStart);
}
} // namespace gui
} // namespace yaze

29
src/app/gui/input.h Normal file
View File

@@ -0,0 +1,29 @@
#ifndef YAZE_APP_CORE_INPUT_H
#define YAZE_APP_CORE_INPUT_H
#include <imgui/imgui.h>
#include <imgui/imgui_internal.h>
#include <cstddef>
#include <cstdint>
#include "absl/strings/string_view.h"
namespace yaze {
namespace gui {
IMGUI_API bool InputHex(const char* label, int* data);
IMGUI_API bool InputHexShort(const char* label, int* data);
using ItemLabelFlags = enum ItemLabelFlag {
Left = 1u << 0u,
Right = 1u << 1u,
Default = Left,
};
IMGUI_API void ItemLabel(absl::string_view title, ItemLabelFlags flags);
} // namespace gui
} // namespace yaze
#endif

108
src/app/gui/style.cc Normal file
View File

@@ -0,0 +1,108 @@
#include "style.h"
#include "imgui/imgui.h"
#include "imgui/imgui_internal.h"
namespace yaze {
namespace gui {
void ColorsYaze() {
ImGuiStyle *style = &ImGui::GetStyle();
ImVec4 *colors = style->Colors;
style->WindowPadding = ImVec2(10.f, 10.f);
style->FramePadding = ImVec2(10.f, 3.f);
style->CellPadding = ImVec2(4.f, 5.f);
style->ItemSpacing = ImVec2(10.f, 5.f);
style->ItemInnerSpacing = ImVec2(5.f, 5.f);
style->TouchExtraPadding = ImVec2(0.f, 0.f);
style->IndentSpacing = 20.f;
style->ScrollbarSize = 14.f;
style->GrabMinSize = 15.f;
style->WindowBorderSize = 0.f;
style->ChildBorderSize = 1.f;
style->PopupBorderSize = 1.f;
style->FrameBorderSize = 0.f;
style->TabBorderSize = 0.f;
style->WindowRounding = 0.f;
style->ChildRounding = 0.f;
style->FrameRounding = 5.f;
style->PopupRounding = 0.f;
style->ScrollbarRounding = 5.f;
auto alttpDarkGreen = ImVec4(0.18f, 0.26f, 0.18f, 1.0f);
auto alttpMidGreen = ImVec4(0.28f, 0.36f, 0.28f, 1.0f);
auto allttpLightGreen = ImVec4(0.36f, 0.45f, 0.36f, 1.0f);
auto allttpLightestGreen = ImVec4(0.49f, 0.57f, 0.49f, 1.0f);
colors[ImGuiCol_MenuBarBg] = alttpDarkGreen;
colors[ImGuiCol_TitleBg] = alttpMidGreen;
colors[ImGuiCol_Header] = alttpDarkGreen;
colors[ImGuiCol_HeaderHovered] = allttpLightGreen;
colors[ImGuiCol_HeaderActive] = alttpMidGreen;
colors[ImGuiCol_TitleBgActive] = alttpDarkGreen;
colors[ImGuiCol_TitleBgCollapsed] = alttpMidGreen;
colors[ImGuiCol_Tab] = alttpDarkGreen;
colors[ImGuiCol_TabHovered] = alttpMidGreen;
colors[ImGuiCol_TabActive] = ImVec4(0.347f, 0.466f, 0.347f, 1.000f);
colors[ImGuiCol_Button] = alttpMidGreen;
colors[ImGuiCol_ButtonHovered] = allttpLightestGreen;
colors[ImGuiCol_ButtonActive] = allttpLightGreen;
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.36f, 0.45f, 0.36f, 0.60f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.36f, 0.45f, 0.36f, 0.30f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.36f, 0.45f, 0.36f, 0.40f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.36f, 0.45f, 0.36f, 0.60f);
colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.85f);
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f);
colors[ImGuiCol_Border] = allttpLightGreen;
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.28f, 0.36f, 0.28f, 0.40f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.28f, 0.36f, 0.28f, 0.69f);
colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.36f, 0.45f, 0.36f, 0.60f);
colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 0.60f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.10f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f);
colors[ImGuiCol_TabUnfocused] =
ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
colors[ImGuiCol_TabUnfocusedActive] =
ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
colors[ImGuiCol_TableHeaderBg] = alttpDarkGreen;
colors[ImGuiCol_TableBorderStrong] = alttpMidGreen;
colors[ImGuiCol_TableBorderLight] =
ImVec4(0.26f, 0.26f, 0.28f, 1.00f); // Prefer using Alpha=1.0 here
colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
}
} // namespace gui
} // namespace yaze

15
src/app/gui/style.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef YAZE_APP_CORE_STYLE_H
#define YAZE_APP_CORE_STYLE_H
#include <imgui/imgui.h>
#include <imgui/imgui_internal.h>
namespace yaze {
namespace gui {
void ColorsYaze();
} // namespace gui
} // namespace yaze
#endif

68
src/app/gui/widgets.cc Normal file
View File

@@ -0,0 +1,68 @@
#include "widgets.h"
#include <ImGuiColorTextEdit/TextEditor.h>
#include "absl/status/status.h"
#include "app/core/constants.h"
namespace yaze {
namespace gui {
namespace widgets {
TextEditor::LanguageDefinition GetAssemblyLanguageDef() {
TextEditor::LanguageDefinition language_65816;
for (auto &k : app::core::kKeywords) language_65816.mKeywords.emplace(k);
for (auto &k : app::core::kIdentifiers) {
TextEditor::Identifier id;
id.mDeclaration = "Built-in function";
language_65816.mIdentifiers.insert(std::make_pair(std::string(k), id));
}
language_65816.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"[ \\t]*#[ \\t]*[a-zA-Z_]+", TextEditor::PaletteIndex::Preprocessor));
language_65816.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"L?\\\"(\\\\.|[^\\\"])*\\\"", TextEditor::PaletteIndex::String));
language_65816.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"\\'\\\\?[^\\']\\'", TextEditor::PaletteIndex::CharLiteral));
language_65816.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)([eE][+-]?[0-9]+)?[fF]?",
TextEditor::PaletteIndex::Number));
language_65816.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"[+-]?[0-9]+[Uu]?[lL]?[lL]?", TextEditor::PaletteIndex::Number));
language_65816.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"0[0-7]+[Uu]?[lL]?[lL]?", TextEditor::PaletteIndex::Number));
language_65816.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"0[xX][0-9a-fA-F]+[uU]?[lL]?[lL]?",
TextEditor::PaletteIndex::Number));
language_65816.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"[a-zA-Z_][a-zA-Z0-9_]*", TextEditor::PaletteIndex::Identifier));
language_65816.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"[\\[\\]\\{\\}\\!\\%\\^\\&\\*\\(\\)\\-\\+\\=\\~\\|\\<\\>\\?\\/"
"\\;\\,\\.]",
TextEditor::PaletteIndex::Punctuation));
language_65816.mCommentStart = "/*";
language_65816.mCommentEnd = "*/";
language_65816.mSingleLineComment = ";";
language_65816.mCaseSensitive = false;
language_65816.mAutoIndentation = true;
language_65816.mName = "65816";
return language_65816;
}
} // namespace widgets
} // namespace gui
} // namespace yaze

19
src/app/gui/widgets.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef YAZE_GUI_WIDGETS_H
#define YAZE_GUI_WIDGETS_H
#include <ImGuiColorTextEdit/TextEditor.h>
#include "absl/status/status.h"
#include "app/core/constants.h"
namespace yaze {
namespace gui {
namespace widgets {
TextEditor::LanguageDefinition GetAssemblyLanguageDef();
} // namespace widgets
} // namespace gui
} // namespace yaze
#endif

View File

@@ -5,7 +5,7 @@
#include "app/gfx/snes_palette.h"
#include "app/gfx/snes_tile.h"
#include "app/rom.h"
#include "gui/canvas.h"
#include "app/gui/canvas.h"
namespace yaze {
namespace app {

View File

@@ -6,7 +6,7 @@
#include "app/gfx/snes_palette.h"
#include "app/gfx/snes_tile.h"
#include "app/rom.h"
#include "gui/canvas.h"
#include "app/gui/canvas.h"
namespace yaze {
namespace app {

View File

@@ -46,20 +46,20 @@ absl::Status Overworld::Load(ROM &rom) {
for (int i = 0; i < core::kNumOverworldMaps; ++i) {
futures.push_back(std::async(std::launch::async, [this, i, size]() {
if (i < 64) {
return overworld_maps_[i].BuildMap(
size, game_state_, 0, map_parent_, map_tiles_.light_world);
return overworld_maps_[i].BuildMap(size, game_state_, 0, map_parent_,
map_tiles_.light_world);
} else if (i < 0x80 && i >= 0x40) {
return overworld_maps_[i].BuildMap(
size, game_state_, 1, map_parent_, map_tiles_.dark_world);
return overworld_maps_[i].BuildMap(size, game_state_, 1, map_parent_,
map_tiles_.dark_world);
} else {
return overworld_maps_[i].BuildMap(
size, game_state_, 2, map_parent_, map_tiles_.special_world);
return overworld_maps_[i].BuildMap(size, game_state_, 2, map_parent_,
map_tiles_.special_world);
}
}));
}
// Wait for all tasks to complete and check their results
for (auto& future : futures) {
for (auto &future : futures) {
absl::Status status = future.get();
if (!status.ok()) {
return status;
@@ -275,110 +275,52 @@ absl::Status Overworld::SaveOverworldMaps() {
// ----------------------------------------------------------------------------
/**
void Overworld::SaveMap16Tiles() {
int tpos = core::map16Tiles;
// 3760
for (int i = 0; i < core::NumberOfMap16; i += 1) {
rom_.WriteShort(tpos, tiles16[i].tile0_);
rom_.WriteShort(tpos, tiles16[i].tile0_.ToShort());
tpos += 2;
rom_.WriteShort(tpos, tiles16[i].tile1_);
rom_.WriteShort(tpos, tiles16[i].tile1_.ToShort());
tpos += 2;
rom_.WriteShort(tpos, tiles16[i].tile2_);
rom_.WriteShort(tpos, tiles16[i].tile2_.ToShort());
tpos += 2;
rom_.WriteShort(tpos, tiles16[i].tile3_);
rom_.WriteShort(tpos, tiles16[i].tile3_.ToShort());
tpos += 2;
}
}
*/
// ----------------------------------------------------------------------------
/**
void Overworld::SaveMap32Tiles() {
int index = 0;
int c = tiles32_unique_.size();
for (int i = 0; i < c; i += 6) {
if (index >= 0x4540) // 3C87??
{
std::cout << "Too many unique tiles!" << std::endl;
const int max_tiles = 0x4540;
const int unique_size = tiles32_unique_.size();
break;
auto write_tiles = [&](int address, auto get_tile) {
for (int i = 0; i < unique_size && i < max_tiles; i += 4) {
for (int j = 0; j < 4; ++j) {
rom_.Write(address + i + j, (uchar)(get_tile(i + j) & 0xFF));
}
rom_.Write(address + i + 4, (uchar)(((get_tile(i) >> 4) & 0xF0) |
((get_tile(i + 1) >> 8) & 0x0F)));
rom_.Write(address + i + 5, (uchar)(((get_tile(i + 2) >> 4) & 0xF0) |
((get_tile(i + 3) >> 8) & 0x0F)));
}
};
// Top Left
rom_.Write(core::map32TilesTL + (i),
(uchar)(tiles32_unique_[index].tile0 & 0xFF));
rom_.Write(core::map32TilesTL + (i + 1),
(uchar)(tiles32_unique_[index + 1].tile0 & 0xFF));
rom_.Write(core::map32TilesTL + (i + 2),
(uchar)(tiles32_unique_[index + 2].tile0 & 0xFF));
rom_.Write(core::map32TilesTL + (i + 3),
(uchar)(tiles32_unique_[index + 3].tile0 & 0xFF));
write_tiles(core::map32TilesTL,
[&](int i) { return tiles32_unique_[i].tile0_; });
write_tiles(core::map32TilesTR,
[&](int i) { return tiles32_unique_[i].tile1_; });
write_tiles(core::map32TilesBL,
[&](int i) { return tiles32_unique_[i].tile2_; });
write_tiles(core::map32TilesBR,
[&](int i) { return tiles32_unique_[i].tile3_; });
rom_.Write(core::map32TilesTL + (i + 4),
(uchar)(((tiles32_unique_[index].tile0 >> 4) & 0xF0) +
((tiles32_unique_[index + 1].tile0 >> 8) & 0x0F)));
rom_.Write(core::map32TilesTL + (i + 5),
(uchar)(((tiles32_unique_[index + 2].tile0 >> 4) & 0xF0) +
((tiles32_unique_[index + 3].tile0 >> 8) & 0x0F)));
// Top Right
rom_.Write(core::map32TilesTR + (i),
(uchar)(tiles32_unique_[index].tile1 & 0xFF));
rom_.Write(core::map32TilesTR + (i + 1),
(uchar)(tiles32_unique_[index + 1].tile1 & 0xFF));
rom_.Write(core::map32TilesTR + (i + 2),
(uchar)(tiles32_unique_[index + 2].tile1 & 0xFF));
rom_.Write(core::map32TilesTR + (i + 3),
(uchar)(tiles32_unique_[index + 3].tile1 & 0xFF));
rom_.Write(core::map32TilesTR + (i + 4),
(uchar)(((tiles32_unique_[index].tile1 >> 4) & 0xF0) |
((tiles32_unique_[index + 1].tile1 >> 8) & 0x0F)));
rom_.Write(core::map32TilesTR + (i + 5),
(uchar)(((tiles32_unique_[index + 2].tile1 >> 4) & 0xF0) |
((tiles32_unique_[index + 3].tile1 >> 8) & 0x0F)));
// Bottom Left
rom_.Write(core::map32TilesBL + (i),
(uchar)(tiles32_unique_[index].tile2 & 0xFF));
rom_.Write(core::map32TilesBL + (i + 1),
(uchar)(tiles32_unique_[index + 1].tile2 & 0xFF));
rom_.Write(core::map32TilesBL + (i + 2),
(uchar)(tiles32_unique_[index + 2].tile2 & 0xFF));
rom_.Write(core::map32TilesBL + (i + 3),
(uchar)(tiles32_unique_[index + 3].tile2 & 0xFF));
rom_.Write(core::map32TilesBL + (i + 4),
(uchar)(((tiles32_unique_[index].tile2 >> 4) & 0xF0) |
((tiles32_unique_[index + 1].tile2 >> 8) & 0x0F)));
rom_.Write(core::map32TilesBL + (i + 5),
(uchar)(((tiles32_unique_[index + 2].tile2 >> 4) & 0xF0) |
((tiles32_unique_[index + 3].tile2 >> 8) & 0x0F)));
// Bottom Right
rom_.Write(core::map32TilesBR + (i),
(uchar)(tiles32_unique_[index].tile3 & 0xFF));
rom_.Write(core::map32TilesBR + (i + 1),
(uchar)(tiles32_unique_[index + 1].tile3 & 0xFF));
rom_.Write(core::map32TilesBR + (i + 2),
(uchar)(tiles32_unique_[index + 2].tile3 & 0xFF));
rom_.Write(core::map32TilesBR + (i + 3),
(uchar)(tiles32_unique_[index + 3].tile3 & 0xFF));
rom_.Write(core::map32TilesBR + (i + 4),
(uchar)(((tiles32_unique_[index].tile3 >> 4) & 0xF0) |
((tiles32_unique_[index + 1].tile3 >> 8) & 0x0F)));
rom_.Write(core::map32TilesBR + (i + 5),
(uchar)(((tiles32_unique_[index + 2].tile3 >> 4) & 0xF0) |
((tiles32_unique_[index + 3].tile3 >> 8) & 0x0F)));
index += 4;
c += 2;
if (unique_size > max_tiles) {
std::cout << "Too many unique tiles!" << std::endl;
}
}
*/
// ----------------------------------------------------------------------------

View File

@@ -13,7 +13,7 @@
#include "app/gfx/snes_tile.h"
#include "app/rom.h"
#include "app/zelda3/overworld_map.h"
#include "app/zelda3/sprite.h"
#include "app/zelda3/sprite/sprite.h"
namespace yaze {
namespace app {

View File

@@ -109,8 +109,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current,
k = 0;
for (int y = 9; y < 13; y++) {
for (int x = 1; x < 16; x++) {
new_palette[x + (16 * y)] = rom.GetPaletteGroup("global_sprites")[0][k];
k++;
new_palette[x + (16 * y)] =
rom.GetPaletteGroup("global_sprites")[0][k]; k++;
}
}
@@ -267,210 +267,156 @@ void OverworldMap::LoadAreaInfo() {
}
}
void OverworldMap::LoadAreaGraphics() {
int world_index = 0x20;
void OverworldMap::LoadWorldIndex() {
if (parent_ < 0x40) {
world_index = 0x20;
world_index_ = 0x20;
} else if (parent_ >= 0x40 && parent_ < 0x80) {
world_index = 0x21;
world_index_ = 0x21;
} else if (parent_ == 0x88) {
world_index = 0x24;
world_index_ = 0x24;
}
}
void OverworldMap::LoadSpritesBlocksets() {
int static_graphics_base = 0x73;
static_graphics_[8] = static_graphics_base + 0x00;
static_graphics_[9] = static_graphics_base + 0x01;
static_graphics_[10] = static_graphics_base + 0x06;
static_graphics_[11] = static_graphics_base + 0x07;
// Sprites Blocksets
static_graphics_[8] = 0x73 + 0x00;
static_graphics_[9] = 0x73 + 0x01;
static_graphics_[10] = 0x73 + 0x06;
static_graphics_[11] = 0x73 + 0x07;
for (int i = 0; i < 4; i++) {
static_graphics_[12 + i] = (rom_[core::kSpriteBlocksetPointer +
(sprite_graphics_[game_state_] * 4) + i] +
0x73);
static_graphics_base);
}
}
// Main Blocksets
void OverworldMap::LoadMainBlocksets() {
for (int i = 0; i < 8; i++) {
static_graphics_[i] =
rom_[core::overworldgfxGroups2 + (world_index * 8) + i];
rom_[core::overworldgfxGroups2 + (world_index_ * 8) + i];
}
}
if (rom_[core::overworldgfxGroups + (area_graphics_ * 4)] != 0) {
static_graphics_[3] = rom_[core::overworldgfxGroups + (area_graphics_ * 4)];
}
if (rom_[core::overworldgfxGroups + (area_graphics_ * 4) + 1] != 0) {
static_graphics_[4] =
rom_[core::overworldgfxGroups + (area_graphics_ * 4) + 1];
}
if (rom_[core::overworldgfxGroups + (area_graphics_ * 4) + 2] != 0) {
static_graphics_[5] =
rom_[core::overworldgfxGroups + (area_graphics_ * 4) + 2];
}
if (rom_[core::overworldgfxGroups + (area_graphics_ * 4) + 3] != 0) {
static_graphics_[6] =
rom_[core::overworldgfxGroups + (area_graphics_ * 4) + 3];
void OverworldMap::LoadAreaGraphicsBlocksets() {
for (int i = 0; i < 4; i++) {
uchar value = rom_[core::overworldgfxGroups + (area_graphics_ * 4) + i];
if (value != 0) {
static_graphics_[3 + i] = value;
}
}
}
// Hardcoded overworld GFX Values, for death mountain
if ((parent_ >= 0x03 && parent_ <= 0x07) ||
(parent_ >= 0x0B && parent_ <= 0x0E)) {
static_graphics_[7] = 0x59;
} else if ((parent_ >= 0x43 && parent_ <= 0x47) ||
(parent_ >= 0x4B && parent_ <= 0x4E)) {
static_graphics_[7] = 0x59;
void OverworldMap::LoadDeathMountainGFX() {
static_graphics_[7] = (((parent_ >= 0x03 && parent_ <= 0x07) ||
(parent_ >= 0x0B && parent_ <= 0x0E)) ||
((parent_ >= 0x43 && parent_ <= 0x47) ||
(parent_ >= 0x4B && parent_ <= 0x4E)))
? 0x59
: 0x5B;
}
void OverworldMap::LoadAreaGraphics() {
LoadWorldIndex();
LoadSpritesBlocksets();
LoadMainBlocksets();
LoadAreaGraphicsBlocksets();
LoadDeathMountainGFX();
}
// New helper function to get a palette from the ROM.
gfx::SNESPalette OverworldMap::GetPalette(const std::string& group, int index,
int previousIndex, int limit) {
if (index == 255) {
index = rom_[core::overworldMapPaletteGroup + (previousIndex * 4)];
}
if (index != 255) {
if (index >= limit) {
index = limit - 1;
}
return rom_.GetPaletteGroup(group)[index];
} else {
static_graphics_[7] = 0x5B;
return rom_.GetPaletteGroup(group)[0];
}
}
void OverworldMap::LoadPalette() {
int previousPalId = 0;
int previousSprPalId = 0;
if (index_ > 0) {
previousPalId = rom_[core::overworldMapPalette + parent_ - 1];
previousSprPalId = rom_[core::overworldSpritePalette + parent_ - 1];
}
int previousPalId =
index_ > 0 ? rom_[core::overworldMapPalette + parent_ - 1] : 0;
int previousSprPalId =
index_ > 0 ? rom_[core::overworldSpritePalette + parent_ - 1] : 0;
if (area_palette_ >= 0xA3) {
area_palette_ = 0xA3;
}
area_palette_ = std::min(area_palette_, 0xA3);
uchar pal0 = 0;
uchar pal1 = rom_[core::overworldMapPaletteGroup + (area_palette_ * 4)];
uchar pal2 =
rom_[core::overworldMapPaletteGroup + (area_palette_ * 4) + 1]; // aux2
uchar pal3 = rom_[core::overworldMapPaletteGroup + (area_palette_ * 4) +
2]; // animated
uchar pal2 = rom_[core::overworldMapPaletteGroup + (area_palette_ * 4) + 1];
uchar pal3 = rom_[core::overworldMapPaletteGroup + (area_palette_ * 4) + 2];
uchar pal4 = rom_[core::overworldSpritePaletteGroup +
(sprite_palette_[game_state_] * 2)]; // spr3
(sprite_palette_[game_state_] * 2)];
uchar pal5 = rom_[core::overworldSpritePaletteGroup +
(sprite_palette_[game_state_] * 2) + 1]; // spr4
(sprite_palette_[game_state_] * 2) + 1];
gfx::SNESPalette aux1;
gfx::SNESPalette aux2;
gfx::SNESPalette main;
gfx::SNESPalette animated;
gfx::SNESPalette hud;
gfx::SNESPalette spr;
gfx::SNESPalette spr2;
gfx::SNESColor bgr = rom_.GetPaletteGroup("grass")[0].GetColor(0);
if (pal1 == 255) {
pal1 = rom_[core::overworldMapPaletteGroup + (previousPalId * 4)];
}
if (pal1 != 255) {
if (pal1 >= 20) {
pal1 = 19;
}
aux1 = rom_.GetPaletteGroup("ow_aux")[pal1];
} else {
aux1 = rom_.GetPaletteGroup("ow_aux")[0];
}
if (pal2 == 255) {
pal2 = rom_[core::overworldMapPaletteGroup + (previousPalId * 4) + 1];
}
if (pal2 != 255) {
if (pal2 >= 20) {
pal2 = 19;
}
aux2 = rom_.GetPaletteGroup("ow_aux")[pal2];
} else {
aux2 = rom_.GetPaletteGroup("ow_aux")[0];
}
gfx::SNESPalette aux1 = GetPalette("ow_aux", pal1, previousPalId, 20);
gfx::SNESPalette aux2 = GetPalette("ow_aux", pal2, previousPalId, 20);
// Additional handling of `pal3` and `parent_`
if (pal3 == 255) {
pal3 = rom_[core::overworldMapPaletteGroup + (previousPalId * 4) + 2];
}
if (parent_ < 0x40) {
// Default LW Palette
pal0 = 0;
pal0 = parent_ == 0x03 || parent_ == 0x05 || parent_ == 0x07 ? 2 : 0;
bgr = rom_.GetPaletteGroup("grass")[0].GetColor(0);
if (parent_ == 0x03 || parent_ == 0x05 || parent_ == 0x07) {
pal0 = 2;
}
} else if (parent_ >= 0x40 && parent_ < 0x80) {
// Default DW Palette
pal0 = 1;
pal0 = parent_ == 0x43 || parent_ == 0x45 || parent_ == 0x47 ? 3 : 1;
bgr = rom_.GetPaletteGroup("grass")[0].GetColor(1);
if (parent_ == 0x43 || parent_ == 0x45 || parent_ == 0x47) {
pal0 = 3;
}
} else if (parent_ >= 128 && parent_ < core::kNumOverworldMaps) {
// Default SP Palette
pal0 = 0;
bgr = rom_.GetPaletteGroup("grass")[0].GetColor(2);
}
if (parent_ == 0x88) {
pal0 = 4;
}
gfx::SNESPalette main = GetPalette("ow_main", pal0, previousPalId, 255);
gfx::SNESPalette animated =
GetPalette("ow_animated", std::min((int)pal3, 13), previousPalId, 14);
gfx::SNESPalette hud = rom_.GetPaletteGroup("hud")[0];
if (pal0 != 255) {
main = rom_.GetPaletteGroup("ow_main")[pal0];
} else {
main = rom_.GetPaletteGroup("ow_main")[0];
}
if (pal3 >= 14) {
pal3 = 13;
}
animated = rom_.GetPaletteGroup("ow_animated")[(pal3)];
hud = rom_.GetPaletteGroup("hud")[0];
if (pal4 == 255) {
pal4 = rom_[core::overworldSpritePaletteGroup +
(previousSprPalId * 2)]; // spr3
}
if (pal4 == 255) {
pal4 = 0;
}
if (pal4 >= 24) {
pal4 = 23;
}
spr = rom_.GetPaletteGroup("sprites_aux3")[pal4];
if (pal5 == 255) {
pal5 = rom_[core::overworldSpritePaletteGroup + (previousSprPalId * 2) +
1]; // spr3
}
if (pal5 == 255) {
pal5 = 0;
}
if (pal5 >= 24) {
pal5 = 23;
}
spr2 = rom_.GetPaletteGroup("sprites_aux3")[pal5];
gfx::SNESPalette spr = GetPalette("sprites_aux3", pal4, previousSprPalId, 24);
gfx::SNESPalette spr2 =
GetPalette("sprites_aux3", pal5, previousSprPalId, 24);
SetColorsPalette(rom_, parent_, current_palette_, main, animated, aux1, aux2,
hud, bgr, spr, spr2);
}
// New helper function to process graphics buffer.
void OverworldMap::ProcessGraphicsBuffer(int index, int static_graphics_offset,
int size) {
for (int i = 0; i < size; i++) {
auto byte = all_gfx_[i + (static_graphics_offset * size)];
switch (index) {
case 0:
case 3:
case 4:
case 5:
byte += 0x88;
break;
}
current_gfx_[(index * size) + i] = byte;
}
}
absl::Status OverworldMap::BuildTileset() {
all_gfx_ = rom_.GetGraphicsBuffer();
current_gfx_.reserve(0x10000);
for (int i = 0; i < 0x10000; i++) {
current_gfx_.push_back(0x00);
}
current_gfx_.resize(0x10000, 0x00);
for (int i = 0; i < 0x10; i++) {
for (int j = 0; j < 0x1000; j++) {
auto byte = all_gfx_[j + (static_graphics_[i] * 0x1000)];
switch (i) {
case 0:
case 3:
case 4:
case 5:
byte += 0x88;
break;
}
current_gfx_[(i * 0x1000) + j] = byte;
}
ProcessGraphicsBuffer(i, static_graphics_[i], 0x1000);
}
return absl::OkStatus();
}

View File

@@ -13,6 +13,7 @@
#include "app/core/common.h"
#include "app/gfx/bitmap.h"
#include "app/gfx/snes_tile.h"
#include "app/gfx/snes_palette.h"
#include "app/rom.h"
namespace yaze {
@@ -39,9 +40,21 @@ class OverworldMap {
private:
void LoadAreaInfo();
void LoadWorldIndex();
void LoadSpritesBlocksets();
void LoadMainBlocksets();
void LoadAreaGraphicsBlocksets();
void LoadDeathMountainGFX();
void LoadAreaGraphics();
void LoadPalette();
void ProcessGraphicsBuffer(int index, int static_graphics_offset, int size);
gfx::SNESPalette GetPalette(const std::string& group, int index, int previousIndex, int limit);
absl::Status BuildTileset();
absl::Status BuildTiles16Gfx(int count);
absl::Status BuildBitmap(OWBlockset& world_blockset);
@@ -54,6 +67,8 @@ class OverworldMap {
int area_palette_ = 0;
int game_state_ = 0;
int world_index_ = 0;
uchar sprite_graphics_[3];
uchar sprite_palette_[3];
uchar area_music_[4];

View File

@@ -3,7 +3,7 @@
#include "app/gfx/bitmap.h"
#include "app/gfx/snes_tile.h"
#include "app/rom.h"
#include "gui/canvas.h"
#include "app/gui/canvas.h"
namespace yaze {
namespace app {

View File

@@ -5,7 +5,7 @@
#include "app/gfx/snes_tile.h"
#include "app/gfx/snes_palette.h"
#include "app/rom.h"
#include "gui/canvas.h"
#include "app/gui/canvas.h"
namespace yaze {
namespace app {