Skip to content

Commit

Permalink
[WIP] byte colouring
Browse files Browse the repository at this point in the history
  • Loading branch information
solemnwarning committed Apr 27, 2024
1 parent 36b09ab commit 2f9a17a
Show file tree
Hide file tree
Showing 12 changed files with 1,338 additions and 35 deletions.
5 changes: 5 additions & 0 deletions Makefile
Expand Up @@ -351,6 +351,7 @@ APP_OBJS := \
src/BitmapTool.$(BUILD_TYPE).o \
src/buffer.$(BUILD_TYPE).o \
src/BytesPerLineDialog.$(BUILD_TYPE).o \
src/ByteColourMap.$(BUILD_TYPE).o \
src/ByteRangeSet.$(BUILD_TYPE).o \
src/CharacterEncoder.$(BUILD_TYPE).o \
src/CharacterFinder.$(BUILD_TYPE).o \
Expand Down Expand Up @@ -396,6 +397,7 @@ APP_OBJS := \
src/RangeProcessor.$(BUILD_TYPE).o \
src/search.$(BUILD_TYPE).o \
src/SettingsDialog.$(BUILD_TYPE).o \
src/SettingsDialogByteColour.$(BUILD_TYPE).o \
src/SettingsDialogHighlights.$(BUILD_TYPE).o \
src/StringPanel.$(BUILD_TYPE).o \
src/textentrydialog.$(BUILD_TYPE).o \
Expand Down Expand Up @@ -451,6 +453,7 @@ TEST_OBJS := \
src/BitOffset.$(BUILD_TYPE).o \
src/BitmapTool.$(BUILD_TYPE).o \
src/buffer.$(BUILD_TYPE).o \
src/ByteColourMap.$(BUILD_TYPE).o \
src/ByteRangeSet.$(BUILD_TYPE).o \
src/BytesPerLineDialog.$(BUILD_TYPE).o \
src/CharacterEncoder.$(BUILD_TYPE).o \
Expand Down Expand Up @@ -488,6 +491,7 @@ TEST_OBJS := \
src/RangeProcessor.$(BUILD_TYPE).o \
src/search.$(BUILD_TYPE).o \
src/SettingsDialog.$(BUILD_TYPE).o \
src/SettingsDialogByteColour.$(BUILD_TYPE).o \
src/SettingsDialogHighlights.$(BUILD_TYPE).o \
src/StringPanel.$(BUILD_TYPE).o \
src/Tab.$(BUILD_TYPE).o \
Expand All @@ -500,6 +504,7 @@ TEST_OBJS := \
tests/BitmapTool.o \
tests/BitOffset.o \
tests/buffer.o \
tests/ByteColourMap.o \
tests/ByteRangeMap.o \
tests/ByteRangeSet.o \
tests/ByteRangeTree.o \
Expand Down
26 changes: 25 additions & 1 deletion src/AppSettings.cpp
Expand Up @@ -25,7 +25,26 @@ wxDEFINE_EVENT(REHex::PREFERRED_ASM_SYNTAX_CHANGED, wxCommandEvent);
REHex::AppSettings::AppSettings():
preferred_asm_syntax(AsmSyntax::INTEL),
goto_offset_base(GotoOffsetBase::AUTO),
highlight_colours(HighlightColourMap::defaults()) {}
highlight_colours(HighlightColourMap::defaults())
{
ByteColourMap types;
types.set_label("Types");

types.set_colour(0x00, ByteColourMap::Colour::HighlightColour(3));
types.set_colour_range(0x20, 0x7E, ByteColourMap::Colour::HighlightColour(2));
types.set_colour(0x7F, ByteColourMap::Colour::HighlightColour(4));
types.set_colour(0xFF, ByteColourMap::Colour::HighlightColour(0));

byte_colour_maps[1] = types;

ByteColourMap grad1;
grad1.set_label("Gradient test 1");

grad1.set_colour_gradient(0x00, 0x7F, ByteColourMap::Colour::HighlightColour(0), ByteColourMap::Colour::HighlightColour(1));
grad1.set_colour_gradient(0x80, 0xFF, ByteColourMap::Colour::HighlightColour(1), ByteColourMap::Colour::HighlightColour(2));

byte_colour_maps[2] = grad1;
}

REHex::AppSettings::AppSettings(wxConfig *config): AppSettings()
{
Expand Down Expand Up @@ -118,3 +137,8 @@ void REHex::AppSettings::set_highlight_colours(const HighlightColourMap &highlig
{
this->highlight_colours = highlight_colours;
}

const std::map<int, REHex::ByteColourMap> &REHex::AppSettings::get_byte_colour_maps() const
{
return byte_colour_maps;
}
5 changes: 5 additions & 0 deletions src/AppSettings.hpp
Expand Up @@ -18,9 +18,11 @@
#ifndef REHEX_APPSETTINGS_HPP
#define REHEX_APPSETTINGS_HPP

#include <map>
#include <wx/config.h>
#include <wx/wx.h>

#include "ByteColourMap.hpp"
#include "HighlightColourMap.hpp"

namespace REHex
Expand Down Expand Up @@ -56,10 +58,13 @@ namespace REHex
const HighlightColourMap &get_highlight_colours() const;
void set_highlight_colours(const HighlightColourMap &highlight_colours);

const std::map<int, ByteColourMap> &get_byte_colour_maps() const;

private:
AsmSyntax preferred_asm_syntax;
GotoOffsetBase goto_offset_base;
HighlightColourMap highlight_colours;
std::map<int, ByteColourMap> byte_colour_maps;
};

wxDECLARE_EVENT(PREFERRED_ASM_SYNTAX_CHANGED, wxCommandEvent);
Expand Down
245 changes: 245 additions & 0 deletions src/ByteColourMap.cpp
@@ -0,0 +1,245 @@
/* Reverse Engineer's Hex Editor
* Copyright (C) 2024 Daniel Collins <solemnwarning@solemnwarning.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#include "App.hpp"
#include "ByteColourMap.hpp"

const wxString &REHex::ByteColourMap::get_label() const
{
return label;
}

void REHex::ByteColourMap::set_label(const wxString &label)
{
this->label = label;
}

void REHex::ByteColourMap::set_colour(unsigned char byte, Colour colour)
{
Value &elem = bytes[byte];

elem.colour1 = colour;
elem.colour2 = colour;
elem.colour_delta_steps = 0;
elem.colour_delta_pos = 0;
}

void REHex::ByteColourMap::set_colour_range(unsigned char first_byte, unsigned char last_byte, Colour colour)
{
assert(first_byte <= last_byte);

for(int i = first_byte; i <= (int)(last_byte); ++i)
{
set_colour(i, colour);
}
}

void REHex::ByteColourMap::set_colour_gradient(unsigned char first_byte, unsigned char last_byte, Colour first_byte_colour, Colour last_byte_colour)
{
assert(first_byte <= last_byte);

if(first_byte == last_byte)
{
set_colour(first_byte, first_byte_colour);
return;
}
else if(first_byte_colour == last_byte_colour)
{
set_colour_range(first_byte, last_byte, first_byte_colour);
return;
}

int diff = last_byte - first_byte;

for(int i = first_byte; i <= (int)(last_byte); ++i)
{
Value &elem = bytes[i];

elem.colour1 = first_byte_colour;
elem.colour2 = last_byte_colour;
elem.colour_delta_steps = diff;
elem.colour_delta_pos = i - first_byte;
}
}

wxColour REHex::ByteColourMap::get_colour(unsigned char byte) const
{
auto &elem = bytes[byte];

return elem.get_colour();
}

const REHex::ByteColourMap::Value &REHex::ByteColourMap::operator[](unsigned char byte) const
{
return bytes[byte];
}

bool REHex::ByteColourMap::Value::is_single() const
{
return colour_delta_steps == 0;
}

bool REHex::ByteColourMap::Value::is_start() const
{
return colour_delta_pos == 0 && colour_delta_steps > 0;
}

bool REHex::ByteColourMap::Value::is_end() const
{
return colour_delta_pos == colour_delta_steps && colour_delta_steps > 0;
}

wxColour REHex::ByteColourMap::Value::get_colour() const
{
wxColour c1, c2;

if(colour1.is_palette_colour())
{
c1 = (*active_palette)[colour1.palette_colour()];
}
else if(colour1.is_highlight_colour())
{
HighlightColourMap highlight_colours = wxGetApp().settings->get_highlight_colours();
c1 = highlight_colours[colour1.highlight_colour()].primary_colour;
}
else{
abort(); /* Unreachable. */
}

if(colour_delta_steps == 0)
{
return c1;
}

if(colour2.is_palette_colour())
{
c2 = (*active_palette)[colour2.palette_colour()];
}
else if(colour2.is_highlight_colour())
{
HighlightColourMap highlight_colours = wxGetApp().settings->get_highlight_colours();
c2 = highlight_colours[colour2.highlight_colour()].primary_colour;
}
else{
abort(); /* Unreachable. */
}

float alpha = (float)(colour_delta_pos) / (float)(colour_delta_steps);

unsigned char r = wxColour::AlphaBlend(c2.Red(), c1.Red(), alpha);
unsigned char g = wxColour::AlphaBlend(c2.Green(), c1.Green(), alpha);
unsigned char b = wxColour::AlphaBlend(c2.Blue(), c1.Blue(), alpha);

return wxColour(r, g, b);
}

std::string REHex::ByteColourMap::serialise_colour_index(Colour index)
{
char buf[64];

if(index.is_palette_colour() && index.palette_colour() == Palette::PAL_NORMAL_TEXT_FG)
{
strcpy(buf, "PAL_NORMAL_TEXT_FG");
}
else if(index.is_highlight_colour())
{
snprintf(buf, sizeof(buf), "highlight.%zu.primary", index.highlight_colour());
}
else{
throw std::invalid_argument("Unexpected index in REHex::ByteColourMap::serialise_colour_index()");
}

return buf;
}

REHex::ByteColourMap::Colour REHex::ByteColourMap::deserialise_colour_index(const std::string &string)
{
int index;

if(string == "PAL_NORMAL_TEXT_FG")
{
return Colour::PaletteColour(Palette::PAL_NORMAL_TEXT_FG);
}
else if(sscanf(string.c_str(), "highlight.%d.primary", &index) == 1 && index >= 0 && index < (int)(HighlightColourMap::MAX_NUM))
{
return Colour::HighlightColour(index);
}

throw std::invalid_argument("Invalid string passed to REHex::ByteColourMap::deserialise_colour_index()");
}

REHex::ByteColourMap REHex::ByteColourMap::load(const wxConfigBase *config)
{
ByteColourMap map;

map.label = config->Read("label", map.label);

for(int i = 0; i < 256; ++i)
{
char path[8];
snprintf(path, sizeof(path), "%d/", i);

if(!config->HasGroup(path))
{
continue;
}

wxConfigPathChanger scoped_path(config, path);

map.bytes[i].colour1 = deserialise_colour_index(config->Read("colour1", wxEmptyString).ToStdString());
map.bytes[i].colour2 = deserialise_colour_index(config->Read("colour2", wxEmptyString).ToStdString());

map.bytes[i].colour_delta_steps = config->Read("colour_delta_steps", (long)(-1));
map.bytes[i].colour_delta_pos = config->Read("colour_delta_pos", (long)(-1));

if(map.bytes[i].colour_delta_steps < 0
|| map.bytes[i].colour_delta_pos < 0
|| map.bytes[i].colour_delta_pos > map.bytes[i].colour_delta_steps)
{
throw std::invalid_argument("invalid colour_delta_steps/colour_delta_pos values");
}
}

return map;
}

void REHex::ByteColourMap::save(wxConfigBase *config)
{
config->Write("label", label);

for(int i = 0; i < 256; ++i)
{
if(bytes[i] == Value())
{
/* Skip serialising default colours. */
continue;
}

char path[8];
snprintf(path, sizeof(path), "%d/", i);
wxConfigPathChanger scoped_path(config, path);

std::string colour1 = serialise_colour_index(bytes[i].colour1);
std::string colour2 = serialise_colour_index(bytes[i].colour2);

config->Write("colour1", wxString(colour1));
config->Write("colour2", wxString(colour2));

config->Write("colour_delta_steps", (long)(bytes[i].colour_delta_steps));
config->Write("colour_delta_pos", (long)(bytes[i].colour_delta_pos));
}
}

0 comments on commit 2f9a17a

Please sign in to comment.