Skip to content

Commit

Permalink
Many improvements in mem editor
Browse files Browse the repository at this point in the history
  • Loading branch information
drhelius committed Mar 30, 2024
1 parent 72ff9a5 commit 6449660
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 32 deletions.
169 changes: 147 additions & 22 deletions platforms/desktop-shared/imgui/memory_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,31 @@
*/

#include "memory_editor.h"
#include <string>
#include <stdexcept>

GearMemoryEditor::GearMemoryEditor()
MemEditor::MemEditor()
{
m_editing_address = -1;
m_set_keyboard_here = false;
m_selection_start = -1;
m_selection_end = -1;
m_separator_column_width = 8.0f;
m_selection_start = 0;
m_selection_end = 0;
m_bytes_per_row = 16;
m_separator_column_width = 8.0f;;
m_uppercase_hex = true;
m_row_scroll_top = 0;
m_row_scroll_bottom = 0;
m_editing_address = -1;
m_set_keyboard_here = false;
m_uppercase_hex = true;
m_gray_out_zeros = true;
m_preview_data_type = 0;
m_preview_endianess = 0;
}

GearMemoryEditor::~GearMemoryEditor()
MemEditor::~MemEditor()
{

}

void GearMemoryEditor::Draw(uint8_t* mem_data, int mem_size, int base_display_addr)
void MemEditor::Draw(uint8_t* mem_data, int mem_size, int base_display_addr)
{
int total_rows = (mem_size + (m_bytes_per_row - 1)) / m_bytes_per_row;
int separator_count = (m_bytes_per_row - 1) / 4;
Expand All @@ -47,17 +52,52 @@ void GearMemoryEditor::Draw(uint8_t* mem_data, int mem_size, int base_display_ad
int max_chars_per_cell = 2;
ImVec2 character_size = ImGui::CalcTextSize("0");
char buf[16];

ImGui::Text("Selection start: %d", m_selection_start);
ImGui::Text("Selection end: %d", m_selection_end);
ImGui::Text("Scroll top: %d", m_row_scroll_top);
ImGui::Text("Scroll bottom: %d", m_row_scroll_bottom);

if (ImGui::BeginChild("##mem", ImVec2(ImGui::GetContentRegionAvail().x, 0), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav))
ImVec4 addr_color = ImVec4(0.1f,0.9f,0.9f,1.0f);
ImVec4 ascii_color = ImVec4(1.0f,0.502f,0.957f,1.0f);
ImVec4 column_color = ImVec4(1.0f,0.90f,0.05f,1.0f);
ImVec4 normal_color = ImVec4(1.0f,1.0f,1.0f,1.0f);
ImVec4 gray_color = ImVec4(0.4f,0.4f,0.4f,1.0f);
float height_separator = ImGui::GetStyle().ItemSpacing.y;
float footer_height = ImGui::GetFrameHeightWithSpacing() * 4;

if (ImGui::BeginChild("##mem", ImVec2(ImGui::GetContentRegionAvail().x, -footer_height), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav))
{
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0.5, 0));

if (ImGui::BeginTable("##hex", byte_column_count, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoKeepColumnsVisible | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY))
if (ImGui::BeginTable("##header", byte_column_count, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoKeepColumnsVisible))
{
ImGui::TableSetupColumn("ADDR ");
ImGui::TableSetupColumn("");

for (int i = 0; i < m_bytes_per_row; i++) {
if (IsColumnSeparator(i, m_bytes_per_row))
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, m_separator_column_width);

sprintf(buf, "%02X", i);

ImGui::TableSetupColumn(buf, ImGuiTableColumnFlags_WidthFixed, character_size.x * max_chars_per_cell + (6 + byte_cell_padding) * 1);
}

ImGui::TableSetupColumn("");
ImGui::TableSetupColumn("ASCII", ImGuiTableColumnFlags_WidthFixed, (character_size.x + character_cell_padding * 1) * m_bytes_per_row);

ImGui::TableNextRow();

ImGui::TableNextColumn();
ImGui::TextColored(addr_color, "%s", ImGui::TableGetColumnName(0));

for (int i = 1; i < (ImGui::TableGetColumnCount() - 1); i++) {
ImGui::TableNextColumn();
ImGui::TextColored(column_color, "%s", ImGui::TableGetColumnName(i));
}

ImGui::TableNextColumn();
ImGui::TextColored(ascii_color, "%s", ImGui::TableGetColumnName(ImGui::TableGetColumnCount() - 1));

ImGui::EndTable();
}

if (ImGui::BeginTable("##hex", byte_column_count, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoKeepColumnsVisible /*| ImGuiTableFlags_RowBg*/ | ImGuiTableFlags_ScrollY))
{
m_row_scroll_top = ImGui::GetScrollY() / character_size.y;
m_row_scroll_bottom = m_row_scroll_top + (ImGui::GetWindowHeight() / character_size.y);
Expand Down Expand Up @@ -138,7 +178,9 @@ void GearMemoryEditor::Draw(uint8_t* mem_data, int mem_size, int base_display_ad
else
{
ImGui::PushItemWidth((character_size).x);
ImGui::Text("%02X", mem_data[byte_address]);

bool gray_out = m_gray_out_zeros && mem_data[byte_address] == 0;
ImGui::TextColored(gray_out ? gray_color : normal_color, m_uppercase_hex ? "%02X" : "%02x", mem_data[byte_address]);

if (cell_hovered && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{
Expand Down Expand Up @@ -179,7 +221,8 @@ void GearMemoryEditor::Draw(uint8_t* mem_data, int mem_size, int base_display_ad
int byte_address = address + x;
unsigned char c = mem_data[byte_address];

ImGui::Text("%c", (c >= 32 && c < 128) ? c : '.');
bool gray_out = m_gray_out_zeros && (c < 32 || c >= 128);
ImGui::TextColored(gray_out ? gray_color : normal_color, "%c", (c >= 32 && c < 128) ? c : '.');

ImGui::PopItemWidth();
ImGui::PopStyleVar();
Expand All @@ -200,14 +243,17 @@ void GearMemoryEditor::Draw(uint8_t* mem_data, int mem_size, int base_display_ad

}
ImGui::EndChild();

DrawOptions(mem_size, base_display_addr);
DrawDataPreview(m_selection_start, mem_data, mem_size);
}

bool GearMemoryEditor::IsColumnSeparator(int current_column, int column_count)
bool MemEditor::IsColumnSeparator(int current_column, int column_count)
{
return (current_column > 0) && (current_column < column_count) && ((current_column % 4) == 0);
}

void GearMemoryEditor::DrawSelectionFrame(int x, int y, int address, ImVec2 cell_pos, ImVec2 cell_size)
void MemEditor::DrawSelectionFrame(int x, int y, int address, ImVec2 cell_pos, ImVec2 cell_size)
{
ImDrawList* drawList = ImGui::GetWindowDrawList();
ImVec4 frame_color = ImVec4(0.1f,0.9f,0.9f,1.0f);
Expand Down Expand Up @@ -238,7 +284,7 @@ void GearMemoryEditor::DrawSelectionFrame(int x, int y, int address, ImVec2 cell
drawList->AddLine(cell_pos + ImVec2(0, cell_size.y), cell_pos + cell_size + ImVec2(1, 0), ImColor(frame_color), 1);
}

void GearMemoryEditor::HandleSelection(int address, int row)
void MemEditor::HandleSelection(int address, int row)
{
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
{
Expand Down Expand Up @@ -268,3 +314,82 @@ void GearMemoryEditor::HandleSelection(int address, int row)
m_selection_end = tmp;
}
}

void MemEditor::JumpToAddress(int address)
{
ImVec2 character_size = ImGui::CalcTextSize("0");
ImGui::SetScrollY((address / m_bytes_per_row) * character_size.y);
}

void MemEditor::DrawOptions(int mem_size, int base_display_addr)
{
ImVec4 color = ImVec4(0.1f,0.9f,0.9f,1.0f);

ImGui::TextColored(color, "REGION:");
ImGui::SameLine();
ImGui::Text("%04X-%04X", base_display_addr, base_display_addr + mem_size);
ImGui::SameLine();
ImGui::TextColored(color, " SELECTION:");
ImGui::SameLine();
ImGui::Text("%04X-%04X",m_selection_start, m_selection_end);

if (ImGui::Button("Options"))
ImGui::OpenPopup("context");

if (ImGui::BeginPopup("context"))
{
ImGui::Text("Columns: ");
ImGui::SameLine();
ImGui::PushItemWidth(120.0f);
ImGui::SliderInt("##columns", &m_bytes_per_row, 4, 16);
ImGui::Text("Preview as:");
ImGui::SameLine();
ImGui::PushItemWidth(120.0f);
ImGui::Combo("##preview_type", &m_preview_data_type, "Uint8\0Int8\0Uint16\0Int16\0UInt32\0Int32\0\0");
ImGui::Text("Preview as:");
ImGui::SameLine();
ImGui::PushItemWidth(120.0f);
ImGui::Combo("##preview_endianess", &m_preview_endianess, "Little Endian\0Big Endian\0\0");
ImGui::Checkbox("Uppercase hex", &m_uppercase_hex);
ImGui::Checkbox("Gray out zeros", &m_gray_out_zeros);

ImGui::EndPopup();
}

ImGui::SameLine();
ImGui::Text("Go to:");
ImGui::SameLine();
ImGui::PushItemWidth(45);
char goto_address[5] = "";
if (ImGui::InputTextWithHint("##gotoaddr", "XXXX", goto_address, IM_ARRAYSIZE(goto_address), ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue))
{
try
{
JumpToAddress((int)std::stoul(goto_address, 0, 16));
}
catch(const std::invalid_argument&)
{
}
goto_address[0] = 0;
}
}

void MemEditor::DrawDataPreview(int address, uint8_t* mem_data, int mem_size)
{
if (address < 0 || address >= mem_size)
return;

ImVec4 color = ImVec4(0.992f,0.592f,0.122f,1.0f);

ImGui::TextColored(color, "Dec:");
ImGui::SameLine();
ImGui::Text("%d", mem_data[address]);

ImGui::TextColored(color, "Hex:");
ImGui::SameLine();
ImGui::Text("%02X", mem_data[address]);

ImGui::TextColored(color, "Bin:");
ImGui::SameLine();
ImGui::Text("%02X", mem_data[address]);
}
26 changes: 16 additions & 10 deletions platforms/desktop-shared/imgui/memory_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,42 @@
*
*/

#ifndef GEAR_MEMORY_EDITOR_H
#define GEAR_MEMORY_EDITOR_H
#ifndef MEM_EDITOR_H
#define MEM_EDITOR_H

#include <stdint.h>
#include <stdio.h>
#include "imgui.h"

class GearMemoryEditor
class MemEditor
{
public:
GearMemoryEditor();
~GearMemoryEditor();
MemEditor();
~MemEditor();

void Draw(uint8_t* mem_data, int mem_size, int base_display_addr = 0x0000);

private:
bool IsColumnSeparator(int current_column, int column_count);
void DrawSelectionFrame(int x, int y, int address, ImVec2 cellPos, ImVec2 cellSize);
void HandleSelection(int address, int row);
void JumpToAddress(int address);
void DrawOptions(int mem_size, int base_display_addr);
void DrawDataPreview(int address, uint8_t* mem_data, int mem_size);

private:
int m_bytes_per_row;
float m_separator_column_width;
bool m_uppercase_hex;
int m_editing_address;
bool m_set_keyboard_here;
int m_selection_start;
int m_selection_end;
int m_bytes_per_row;
int m_row_scroll_top;
int m_row_scroll_bottom;
int m_editing_address;
bool m_set_keyboard_here;
bool m_uppercase_hex;
bool m_gray_out_zeros;
int m_preview_data_type;
int m_preview_endianess;
};

#endif /* GEAR_MEMORY_EDITOR_H */
#endif /* MEM_EDITOR_H */

0 comments on commit 6449660

Please sign in to comment.