Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
35cad11
commit 44f06e9
Showing
8 changed files
with
919 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
/* 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" | ||
|
||
void REHex::ByteColourMap::set_colour(unsigned char byte, Colour colour1, Colour colour2, int colour_delta_steps, int colour_delta_pos) | ||
{ | ||
auto &elem = bytes[byte]; | ||
|
||
assert(colour_delta_steps >= colour_delta_pos); | ||
|
||
elem.colour1 = colour1; | ||
elem.colour2 = colour2; | ||
elem.colour_delta_steps = colour_delta_steps; | ||
elem.colour_delta_pos = colour_delta_pos; | ||
} | ||
|
||
wxColour REHex::ByteColourMap::get_colour(unsigned char byte) const | ||
{ | ||
auto &elem = bytes[byte]; | ||
|
||
return elem.get_colour(); | ||
} | ||
|
||
const REHex::ByteColourMap::Value &REHex::ByteColourMap::get_value(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(); | ||
c2 = 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)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
/* 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. | ||
*/ | ||
|
||
#ifndef REHEX_BYTECOLOURMAP_HPP | ||
#define REHEX_BYTECOLOURMAP_HPP | ||
|
||
#include <wx/colour.h> | ||
#include <wx/config.h> | ||
|
||
#include "Palette.hpp" | ||
#include "HighlightColourMap.hpp" | ||
|
||
namespace REHex | ||
{ | ||
class ByteColourMap | ||
{ | ||
public: | ||
/** | ||
* @brief A colour from the active palette or application highlight map. | ||
*/ | ||
class Colour | ||
{ | ||
private: | ||
static constexpr int PALETTE_COLOUR_BASE = 0; | ||
static constexpr int PALETTE_COLOUR_MAX = Palette::PAL_MAX; | ||
|
||
static constexpr int HIGHLIGHT_COLOUR_BASE = PALETTE_COLOUR_MAX + 1; | ||
static constexpr int HIGHLIGHT_COLOUR_MAX = HIGHLIGHT_COLOUR_BASE + HighlightColourMap::MAX_NUM - 1; | ||
|
||
int value; | ||
|
||
Colour(int value): value(value) {} | ||
|
||
public: | ||
/** | ||
* @brief Create a Colour for a Palette colour slot. | ||
*/ | ||
static Colour PaletteColour(Palette::ColourIndex colour_idx) | ||
{ | ||
return Colour(PALETTE_COLOUR_BASE + colour_idx); | ||
} | ||
|
||
/** | ||
* @brief Check if this Colour is a Palette colour. | ||
*/ | ||
bool is_palette_colour() const | ||
{ | ||
return value >= HIGHLIGHT_COLOUR_BASE && value <= HIGHLIGHT_COLOUR_MAX; | ||
} | ||
|
||
/** | ||
* @brief Get the Palette colour index from this Colour. | ||
* | ||
* NOTE: Ensure is_palette_colour() is true before calling | ||
* this method. | ||
*/ | ||
Palette::ColourIndex palette_colour() const | ||
{ | ||
assert(is_palette_colour()); | ||
return (Palette::ColourIndex)(value - PALETTE_COLOUR_BASE); | ||
} | ||
|
||
/** | ||
* @brief Create a colour for a highlight primary colour. | ||
*/ | ||
static Colour HighlightColour(size_t highlight_idx) | ||
{ | ||
return Colour(HIGHLIGHT_COLOUR_BASE + highlight_idx); | ||
} | ||
|
||
/** | ||
* @brief Check if this Colour is a highlight (primary) colour. | ||
*/ | ||
bool is_highlight_colour() const | ||
{ | ||
return value >= HIGHLIGHT_COLOUR_BASE && value <= HIGHLIGHT_COLOUR_MAX; | ||
} | ||
|
||
/** | ||
* @brief Get the (primary) highlight colour index from this Colour. | ||
* | ||
* NOTE: Ensure is_highlight_colour() is true before | ||
* calling this method. | ||
*/ | ||
size_t highlight_colour() const | ||
{ | ||
assert(is_highlight_colour()); | ||
return value - HIGHLIGHT_COLOUR_BASE; | ||
} | ||
|
||
bool operator==(const Colour &rhs) const | ||
{ | ||
return value == rhs.value; | ||
} | ||
}; | ||
|
||
struct Value | ||
{ | ||
Colour colour1; | ||
Colour colour2; | ||
|
||
int colour_delta_steps; | ||
int colour_delta_pos; | ||
|
||
Value(): | ||
colour1(Colour::PaletteColour(Palette::PAL_NORMAL_TEXT_FG)), | ||
colour2(Colour::PaletteColour(Palette::PAL_NORMAL_TEXT_FG)), | ||
colour_delta_steps(0), | ||
colour_delta_pos(0) {} | ||
|
||
bool operator==(const Value &rhs) const | ||
{ | ||
return colour1 == rhs.colour1 | ||
&& colour2 == rhs.colour2 | ||
&& colour_delta_steps == rhs.colour_delta_steps | ||
&& colour_delta_pos == rhs.colour_delta_pos; | ||
} | ||
|
||
bool is_single() const; | ||
bool is_start() const; | ||
bool is_end() const; | ||
|
||
wxColour get_colour() const; | ||
}; | ||
|
||
private: | ||
wxString label; | ||
Value bytes[256]; | ||
|
||
static std::string serialise_colour_index(Colour index); | ||
static Colour deserialise_colour_index(const std::string &string); | ||
|
||
public: | ||
const wxString &get_label() const; | ||
void set_label(const wxString &label); | ||
|
||
void set_colour(unsigned char byte, Colour colour1, Colour colour2, int colour_delta_steps, int colour_delta_pos); | ||
|
||
wxColour get_colour(unsigned char byte) const; | ||
|
||
const Value &get_value(unsigned char byte) const; | ||
|
||
static ByteColourMap load(const wxConfigBase *config); | ||
void save(wxConfigBase *config); | ||
}; | ||
} | ||
|
||
#endif /* !REHEX_BYTECOLOURMAP_HPP */ |
Oops, something went wrong.