added interactive palette display to VideoDialog

This commit is contained in:
thrust26 2020-05-10 19:53:59 +02:00
parent b21efb6269
commit 85f438f693
6 changed files with 274 additions and 142 deletions

View File

@ -46,7 +46,7 @@ PaletteHandler::PaletteType PaletteHandler::toPaletteType(const string& name) co
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string PaletteHandler::toPaletteName(PaletteType type) const
{
string SETTING_NAMES[int(PaletteType::NumTypes)] = {
const string SETTING_NAMES[int(PaletteType::NumTypes)] = {
SETTING_STANDARD, SETTING_Z26, SETTING_USER, SETTING_CUSTOM
};
@ -56,7 +56,7 @@ string PaletteHandler::toPaletteName(PaletteType type) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::changePalette(bool increase)
{
string MESSAGES[PaletteType::NumTypes] = {
const string MESSAGES[PaletteType::NumTypes] = {
"Standard Stella", "Z26", "User-defined", "Custom"
};
@ -98,7 +98,7 @@ void PaletteHandler::changePalette(bool increase)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::selectAdjustable(bool next)
{
bool isCustomPalette = "custom" == myOSystem.settings().getString("palette");
const bool isCustomPalette = "custom" == myOSystem.settings().getString("palette");
do {
if(next)
@ -154,10 +154,54 @@ void PaletteHandler::changeAdjustable(bool increase)
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::changeColorPhaseShift(bool increase)
{
const ConsoleTiming timing = myOSystem.console().timing();
// SECAM is not supported
if(timing != ConsoleTiming::secam)
{
constexpr char DEGREE = 0x1c;
const bool isNTSC = timing == ConsoleTiming::ntsc;
const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT;
float phase = isNTSC ? myPhaseNTSC : myPhasePAL;
if(increase) // increase color phase shift
{
phase += 0.3F;
phase = std::min(phase, shift + MAX_SHIFT);
}
else // decrease color phase shift
{
phase -= 0.3F;
phase = std::max(phase, shift - MAX_SHIFT);
}
if(isNTSC)
myPhaseNTSC = phase;
else
myPhasePAL = phase;
generateCustomPalette(timing);
setPalette("custom");
ostringstream ss;
ss << "Color phase shift at "
<< std::fixed << std::setprecision(1) << phase << DEGREE;
myOSystem.frameBuffer().showMessage(ss.str());
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::loadConfig(const Settings& settings)
{
// Load adjustables
myPhaseNTSC = BSPF::clamp(settings.getFloat("tv.phase_ntsc"),
DEF_NTSC_SHIFT - MAX_SHIFT, DEF_NTSC_SHIFT + MAX_SHIFT);
myPhasePAL = BSPF::clamp(settings.getFloat("tv.phase_pal"),
DEF_PAL_SHIFT - MAX_SHIFT, DEF_PAL_SHIFT + MAX_SHIFT);
myHue = BSPF::clamp(settings.getFloat("tv.hue"), -1.0F, 1.0F);
mySaturation = BSPF::clamp(settings.getFloat("tv.saturation"), -1.0F, 1.0F);
myContrast = BSPF::clamp(settings.getFloat("tv.contrast"), -1.0F, 1.0F);
@ -169,6 +213,9 @@ void PaletteHandler::loadConfig(const Settings& settings)
void PaletteHandler::saveConfig(Settings& settings) const
{
// Save adjustables
settings.setValue("tv.phase_ntsc", myPhaseNTSC);
settings.setValue("tv.phase_pal", myPhasePAL);
settings.setValue("tv.hue", myHue);
settings.setValue("tv.saturation", mySaturation);
settings.setValue("tv.contrast", myContrast);
@ -177,8 +224,11 @@ void PaletteHandler::saveConfig(Settings& settings) const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::setAdjustables(Adjustable& adjustable)
void PaletteHandler::setAdjustables(const Adjustable& adjustable)
{
myPhaseNTSC = adjustable.phaseNtsc / 10.F;
myPhasePAL = adjustable.phasePal / 10.F;
myHue = scaleFrom100(adjustable.hue);
mySaturation = scaleFrom100(adjustable.saturation);
myContrast = scaleFrom100(adjustable.contrast);
@ -189,6 +239,9 @@ void PaletteHandler::setAdjustables(Adjustable& adjustable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::getAdjustables(Adjustable& adjustable) const
{
adjustable.phaseNtsc = myPhaseNTSC * 10.F;
adjustable.phasePal = myPhasePAL * 10.F;
adjustable.hue = scaleTo100(myHue);
adjustable.saturation = scaleTo100(mySaturation);
adjustable.contrast = scaleTo100(myContrast);
@ -196,46 +249,6 @@ void PaletteHandler::getAdjustables(Adjustable& adjustable) const
adjustable.gamma = scaleTo100(myGamma);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::changeColorPhaseShift(bool increase)
{
const ConsoleTiming timing = myOSystem.console().timing();
// SECAM is not supported
if(timing != ConsoleTiming::secam)
{
const char DEGREE = 0x1c;
const float NTSC_SHIFT = 26.2F;
const float PAL_SHIFT = 31.3F; // 360 / 11.5
const bool isNTSC = timing == ConsoleTiming::ntsc;
const string key = isNTSC ? "tv.phase_ntsc" : "tv.phase_pal";
const float shift = isNTSC ? NTSC_SHIFT : PAL_SHIFT;
float phase = myOSystem.settings().getFloat(key);
if(increase) // increase color phase shift
{
phase += 0.3F;
phase = std::min(phase, shift + 4.5F);
}
else // decrease color phase shift
{
phase -= 0.3F;
phase = std::max(phase, shift - 4.5F);
}
myOSystem.settings().setValue(key, phase);
generateCustomPalette(timing);
setPalette("custom");
ostringstream ss;
ss << "Color phase shift at "
<< std::fixed << std::setprecision(1) << phase << DEGREE;
myOSystem.frameBuffer().showMessage(ss.str());
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::setPalette(const string& name)
{
@ -251,7 +264,7 @@ void PaletteHandler::setPalette()
// Look at all the palettes, since we don't know which one is
// currently active
static constexpr BSPF::array2D<PaletteArray*, PaletteType::NumTypes, int(ConsoleTiming::numTimings)> palettes = {{
static constexpr BSPF::array2D<const PaletteArray*, PaletteType::NumTypes, int(ConsoleTiming::numTimings)> palettes = {{
{ &ourNTSCPalette, &ourPALPalette, &ourSECAMPalette },
{ &ourNTSCPaletteZ26, &ourPALPaletteZ26, &ourSECAMPaletteZ26 },
{ &ourUserNTSCPalette, &ourUserPALPalette, &ourUserSECAMPalette },
@ -274,19 +287,19 @@ PaletteArray PaletteHandler::adjustPalette(const PaletteArray& palette)
{
PaletteArray destPalette;
// Constants for saturation and gray scale calculation
const float PR = .2989F;
const float PG = .5870F;
const float PB = .1140F;
constexpr float PR = .2989F;
constexpr float PG = .5870F;
constexpr float PB = .1140F;
// Generate adjust table
const int ADJUST_SIZE = 256;
const int RGB_UNIT = 1 << 8;
const float RGB_OFFSET = 0.5F;
constexpr int ADJUST_SIZE = 256;
constexpr int RGB_UNIT = 1 << 8;
constexpr float RGB_OFFSET = 0.5F;
const float brightness = myBrightness * (0.5F * RGB_UNIT) + RGB_OFFSET;
const float contrast = myContrast * (0.5F * RGB_UNIT) + RGB_UNIT;
const float saturation = mySaturation + 1;
const float gamma = 1.1333F - myGamma * 0.5F;
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
const float toFloat = 1.F / (ADJUST_SIZE - 1);
constexpr float toFloat = 1.F / (ADJUST_SIZE - 1);
std::array<float, ADJUST_SIZE> adjust;
for(int i = 0; i < ADJUST_SIZE; i++)
@ -341,13 +354,13 @@ void PaletteHandler::loadUserPalette()
for(int i = 0; i < 128; i++) // NTSC palette
{
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
ourUserNTSCPalette[(i<<1)] = pixel;
}
for(int i = 0; i < 128; i++) // PAL palette
{
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
ourUserPALPalette[(i<<1)] = pixel;
}
@ -355,7 +368,7 @@ void PaletteHandler::loadUserPalette()
for(int i = 0; i < 8; i++) // SECAM palette
{
in.read(reinterpret_cast<char*>(pixbuf.data()), 3);
uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
secam[(i<<1)] = pixel;
secam[(i<<1)+1] = 0;
}
@ -383,8 +396,7 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
{
// YIQ is YUV shifted by 33°
constexpr float offset = 33 * (2 * BSPF::PI_f / 360);
const float shift = myOSystem.settings().getFloat("tv.phase_ntsc") *
(2 * BSPF::PI_f / 360);
const float shift = myPhaseNTSC * (2 * BSPF::PI_f / 360);
// color 0 is grayscale
for(int chroma = 1; chroma < NUM_CHROMA; chroma++)
@ -429,8 +441,7 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
else if(timing == ConsoleTiming::pal)
{
constexpr float offset = 180 * (2 * BSPF::PI_f / 360);
float shift = myOSystem.settings().getFloat("tv.phase_pal") *
(2 * BSPF::PI_f / 360);
const float shift = myPhasePAL * (2 * BSPF::PI_f / 360);
constexpr float fixedShift = 22.5F * (2 * BSPF::PI_f / 360);
// colors 0, 1, 14 and 15 are grayscale
@ -453,11 +464,10 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
{
const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
// Most sources
// Most sources
float R = Y + 1.403F * V;
float G = Y - 0.344F * U - 0.714F * V;
float B = Y + 1.770F * U;
// German Wikipedia, huh???
//float B = Y + 1 / 0.493 * U;
//float R = Y + 1 / 0.877 * V;
@ -504,8 +514,7 @@ void PaletteHandler::changeSaturation(int& R, int& G, int& B, float change)
constexpr float PR = .2989F;
constexpr float PG = .5870F;
constexpr float PB = .1140F;
float P = sqrt(R * R * PR + G * G * PG + B * B * PB) ;
const float P = sqrt(R * R * PR + G * G * PG + B * B * PB) ;
R = P + (R - P) * change;
G = P + (G - P) * change;
@ -517,7 +526,7 @@ void PaletteHandler::changeSaturation(int& R, int& G, int& B, float change)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray PaletteHandler::ourNTSCPalette = {
const PaletteArray PaletteHandler::ourNTSCPalette = {
0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
0xaaaaaa, 0, 0xc0c0c0, 0, 0xd6d6d6, 0, 0xececec, 0,
0x484800, 0, 0x69690f, 0, 0x86861d, 0, 0xa2a22a, 0,
@ -553,7 +562,7 @@ PaletteArray PaletteHandler::ourNTSCPalette = {
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray PaletteHandler::ourPALPalette = {
const PaletteArray PaletteHandler::ourPALPalette = {
0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 180 0
0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, // was 0x111111..0xcccccc
0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 198 1
@ -589,7 +598,7 @@ PaletteArray PaletteHandler::ourPALPalette = {
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray PaletteHandler::ourSECAMPalette = {
const PaletteArray PaletteHandler::ourSECAMPalette = {
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
@ -625,7 +634,7 @@ PaletteArray PaletteHandler::ourSECAMPalette = {
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray PaletteHandler::ourNTSCPaletteZ26 = {
const PaletteArray PaletteHandler::ourNTSCPaletteZ26 = {
0x000000, 0, 0x505050, 0, 0x646464, 0, 0x787878, 0,
0x8c8c8c, 0, 0xa0a0a0, 0, 0xb4b4b4, 0, 0xc8c8c8, 0,
0x445400, 0, 0x586800, 0, 0x6c7c00, 0, 0x809000, 0,
@ -661,7 +670,7 @@ PaletteArray PaletteHandler::ourNTSCPaletteZ26 = {
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray PaletteHandler::ourPALPaletteZ26 = {
const PaletteArray PaletteHandler::ourPALPaletteZ26 = {
0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
@ -697,7 +706,7 @@ PaletteArray PaletteHandler::ourPALPaletteZ26 = {
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteArray PaletteHandler::ourSECAMPaletteZ26 = {
const PaletteArray PaletteHandler::ourSECAMPaletteZ26 = {
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,

View File

@ -20,6 +20,7 @@
#include "bspf.hxx"
#include "OSystem.hxx"
#include "ConsoleTiming.hxx"
class PaletteHandler
{
@ -29,6 +30,10 @@ class PaletteHandler
static constexpr const char* SETTING_USER = "user";
static constexpr const char* SETTING_CUSTOM = "custom";
static constexpr float DEF_NTSC_SHIFT = 26.2F;
static constexpr float DEF_PAL_SHIFT = 31.3F; // 360 / 11.5
static constexpr float MAX_SHIFT = 4.5F;
enum DisplayType {
NTSC,
PAL,
@ -37,6 +42,7 @@ class PaletteHandler
};
struct Adjustable {
float phaseNtsc, phasePal;
uInt32 hue, saturation, contrast, brightness, gamma;
};
@ -55,7 +61,7 @@ class PaletteHandler
void loadConfig(const Settings& settings);
void saveConfig(Settings& settings) const;
void setAdjustables(Adjustable& adjustable);
void setAdjustables(const Adjustable& adjustable);
void getAdjustables(Adjustable& adjustable) const;
/**
@ -114,7 +120,7 @@ class PaletteHandler
private:
static const int NUM_ADJUSTABLES = 6;
static constexpr int NUM_ADJUSTABLES = 6;
OSystem& myOSystem;
@ -133,11 +139,13 @@ class PaletteHandler
{ "gamma", &myGamma },
} };
float myPhaseNTSC{0.0F};
float myPhasePAL{0.0F};
// range -1.0 to +1.0 (as in AtariNTSC)
// Basic parameters
float myContrast{0.0F}; // -1 = dark (0.5) +1 = light (1.5)
float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees
float mySaturation{0.0F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0)
float myContrast{0.0F}; // -1 = dark (0.5) +1 = light (1.5)
float myBrightness{0.0F}; // -1 = dark (0.5) +1 = light (1.5)
// Advanced parameters
float myGamma{0.0F}; // -1 = dark (1.5) +1 = light (0.5)
@ -147,14 +155,14 @@ class PaletteHandler
bool myUserPaletteDefined{false};
// Table of RGB values for NTSC, PAL and SECAM
static PaletteArray ourNTSCPalette;
static PaletteArray ourPALPalette;
static PaletteArray ourSECAMPalette;
static const PaletteArray ourNTSCPalette;
static const PaletteArray ourPALPalette;
static const PaletteArray ourSECAMPalette;
// Table of RGB values for NTSC, PAL and SECAM - Z26 version
static PaletteArray ourNTSCPaletteZ26;
static PaletteArray ourPALPaletteZ26;
static PaletteArray ourSECAMPaletteZ26;
static const PaletteArray ourNTSCPaletteZ26;
static const PaletteArray ourPALPaletteZ26;
static const PaletteArray ourSECAMPaletteZ26;
// Table of RGB values for NTSC, PAL and SECAM - user-defined
static PaletteArray ourUserNTSCPalette;

View File

@ -25,10 +25,11 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ColorWidget::ColorWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int w, int h, int cmd)
int x, int y, int w, int h, int cmd, bool framed)
: Widget(boss, font, x, y, w, h),
CommandSender(boss),
_cmd(cmd)
_cmd(cmd),
_framed(framed)
{
_flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS;
}
@ -46,11 +47,18 @@ void ColorWidget::drawWidget(bool hilite)
FBSurface& s = dialog().surface();
bool onTop = _boss->dialog().isOnTop();
if(_framed)
{
// Draw a thin frame around us.
s.frameRect(_x, _y, _w, _h + 1, kColor);
s.frameRect(_x, _y, _w, _h + 1, kColor);
// Show the currently selected color
s.fillRect(_x+1, _y+1, _w-2, _h-1, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo);
// Show the currently selected color
s.fillRect(_x + 1, _y + 1, _w - 2, _h - 1, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo);
}
else
{
s.fillRect(_x, _y, _w, _h, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo);
}
// Cross out the grid?
if(_crossGrid)

View File

@ -36,7 +36,7 @@ class ColorWidget : public Widget, public CommandSender
public:
ColorWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int w, int h, int cmd = 0);
int x, int y, int w, int h, int cmd = 0, bool framed = true);
virtual ~ColorWidget() = default;
void setColor(ColorId color);
@ -49,6 +49,7 @@ class ColorWidget : public Widget, public CommandSender
protected:
ColorId _color{kNone};
bool _framed{true};
int _cmd{0};
bool _crossGrid{false};

View File

@ -18,12 +18,14 @@
#include <cmath>
#include "bspf.hxx"
#include "Base.hxx"
#include "Control.hxx"
#include "Dialog.hxx"
#include "Menu.hxx"
#include "OSystem.hxx"
#include "EditTextWidget.hxx"
#include "PopUpWidget.hxx"
#include "ColorWidget.hxx"
#include "Console.hxx"
#include "PaletteHandler.hxx"
#include "TIA.hxx"
@ -104,6 +106,14 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
addPaletteTab();
addTVEffectsTab();
//const int req_w = std::max(myFastSCBios->getRight(), myCloneBad->getRight()) + HBORDER + 1;
//const int req_h = _th + VGAP * 3
// + std::max(myUseVSync->getBottom(), myTVScanIntense->getBottom())
// + buttonHeight + VBORDER * 2;
//// Set real dimensions
//setSize(req_w, req_h, max_w, max_h);
// Add Defaults, OK and Cancel buttons
WidgetArray wid;
addDefaultsOKCancelBGroup(wid, _font);
@ -266,7 +276,8 @@ void VideoDialog::addPaletteTab()
myPhaseShiftNtsc =
new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight,
"NTSC phase", plWidth, kNtscShiftChanged, fontWidth * 5);
myPhaseShiftNtsc->setMinValue(262 - 45); myPhaseShiftNtsc->setMaxValue(262 + 45);
myPhaseShiftNtsc->setMinValue((PaletteHandler::DEF_NTSC_SHIFT - PaletteHandler::MAX_SHIFT) * 10);
myPhaseShiftNtsc->setMaxValue((PaletteHandler::DEF_NTSC_SHIFT + PaletteHandler::MAX_SHIFT) * 10);
myPhaseShiftNtsc->setTickmarkIntervals(4);
wid.push_back(myPhaseShiftNtsc);
ypos += lineHeight + VGAP;
@ -274,7 +285,8 @@ void VideoDialog::addPaletteTab()
myPhaseShiftPal =
new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight,
"PAL phase", plWidth, kPalShiftChanged, fontWidth * 5);
myPhaseShiftPal->setMinValue(313 - 45); myPhaseShiftPal->setMaxValue(313 + 45);
myPhaseShiftPal->setMinValue((PaletteHandler::DEF_PAL_SHIFT - PaletteHandler::MAX_SHIFT) * 10);
myPhaseShiftPal->setMaxValue((PaletteHandler::DEF_PAL_SHIFT + PaletteHandler::MAX_SHIFT) * 10);
myPhaseShiftPal->setTickmarkIntervals(4);
wid.push_back(myPhaseShiftPal);
ypos += lineHeight + VGAP;
@ -288,11 +300,15 @@ void VideoDialog::addPaletteTab()
wid.push_back(myTV ## obj); \
ypos += lineHeight + VGAP;
CREATE_CUSTOM_SLIDERS(Hue, "Hue ", 0)
CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", 0)
CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", 0)
CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", 0)
CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", 0)
CREATE_CUSTOM_SLIDERS(Hue, "Hue ", kPaletteUpdated)
CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", kPaletteUpdated)
CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", kPaletteUpdated)
CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", kPaletteUpdated)
CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", kPaletteUpdated)
// The resulting palette
addPalette(myPhaseShiftNtsc->getRight() + fontWidth * 2, VBORDER,
fontWidth * 2 * 8, myTVGamma->getBottom() - myTIAPalette->getTop());
// Add items for tab 2
addToFocusList(wid, myTab, tabID);
@ -412,13 +428,20 @@ void VideoDialog::loadConfig()
myTIAZoom->setValue(instance().settings().getFloat("tia.zoom") * 100);
// TIA Palette
myTIAPalette->setSelected(
instance().settings().getString("palette"), "standard");
myPalette = instance().settings().getString("palette");
myTIAPalette->setSelected(myPalette, "standard");
// Custom Palette
myPhaseShiftNtsc->setValue(instance().settings().getFloat("tv.phase_ntsc") * 10);
myPhaseShiftPal->setValue(instance().settings().getFloat("tv.phase_pal") * 10);
// Palette adjustables
instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(myPaletteAdj);
myPhaseShiftNtsc->setValue(myPaletteAdj.phaseNtsc);
myPhaseShiftPal->setValue(myPaletteAdj.phasePal);
myTVHue->setValue(myPaletteAdj.hue);
myTVBright->setValue(myPaletteAdj.brightness);
myTVContrast->setValue(myPaletteAdj.contrast);
myTVSatur->setValue(myPaletteAdj.saturation);
myTVGamma->setValue(myPaletteAdj.gamma);
handlePaletteChange();
colorPalette();
// TIA interpolation
myTIAInterpolate->setState(instance().settings().getBool("tia.inter"));
@ -459,15 +482,6 @@ void VideoDialog::loadConfig()
int preset = instance().settings().getInt("tv.filter");
handleTVModeChange(NTSCFilter::Preset(preset));
// Palette adjustables
PaletteHandler::Adjustable paletteAdj;
instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(paletteAdj);
myTVHue->setValue(paletteAdj.hue);
myTVBright->setValue(paletteAdj.brightness);
myTVContrast->setValue(paletteAdj.contrast);
myTVSatur->setValue(paletteAdj.saturation);
myTVGamma->setValue(paletteAdj.gamma);
// TV Custom adjustables
loadTVAdjustables(NTSCFilter::Preset::CUSTOM);
@ -491,31 +505,12 @@ void VideoDialog::saveConfig()
instance().settings().setValue("video",
myRenderer->getSelectedTag().toString());
// TIA zoom levels
instance().settings().setValue("tia.zoom", myTIAZoom->getValue() / 100.0);
// TIA Palette
instance().settings().setValue("palette",
myTIAPalette->getSelectedTag().toString());
// Custom Palette
instance().settings().setValue("tv.phase_ntsc", myPhaseShiftNtsc->getValue() / 10.0);
instance().settings().setValue("tv.phase_pal", myPhaseShiftPal->getValue() / 10.0);
// TIA interpolation
instance().settings().setValue("tia.inter", myTIAInterpolate->getState());
// Aspect ratio setting (NTSC and PAL)
int oldAdjust = instance().settings().getInt("tia.vsizeadjust");
int newAdjust = myVSizeAdjust->getValue();
bool vsizeChanged = oldAdjust != newAdjust;
instance().settings().setValue("tia.vsizeadjust", newAdjust);
// Note: Palette values are saved directly when changed!
// Speed
int speedup = mySpeed->getValue();
instance().settings().setValue("speed", unmapSpeed(speedup));
if (instance().hasConsole()) instance().console().initializeAudio();
// Fullscreen
instance().settings().setValue("fullscreen", myFullscreen->getState());
@ -524,6 +519,22 @@ void VideoDialog::saveConfig()
// Fullscreen overscan
instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel());
// TIA zoom levels
instance().settings().setValue("tia.zoom", myTIAZoom->getValue() / 100.0);
// Aspect ratio setting (NTSC and PAL)
const int oldAdjust = instance().settings().getInt("tia.vsizeadjust");
const int newAdjust = myVSizeAdjust->getValue();
const bool vsizeChanged = oldAdjust != newAdjust;
instance().settings().setValue("tia.vsizeadjust", newAdjust);
// Speed
const int speedup = mySpeed->getValue();
instance().settings().setValue("speed", unmapSpeed(speedup));
if (instance().hasConsole())
instance().console().initializeAudio();
// Use sync to vertical blank
instance().settings().setValue("vsync", myUseVSync->getState());
@ -541,16 +552,6 @@ void VideoDialog::saveConfig()
// TV Mode
instance().settings().setValue("tv.filter",
myTVMode->getSelectedTag().toString());
// Palette adjustables
PaletteHandler::Adjustable paletteAdj;
paletteAdj.hue = myTVHue->getValue();
paletteAdj.saturation = myTVSatur->getValue();
paletteAdj.contrast = myTVContrast->getValue();
paletteAdj.brightness = myTVBright->getValue();
paletteAdj.gamma = myTVGamma->getValue();
instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(paletteAdj);
// TV Custom adjustables
NTSCFilter::Adjustable ntscAdj;
ntscAdj.sharpness = myTVSharp->getValue();
@ -596,32 +597,36 @@ void VideoDialog::setDefaults()
case 0: // General
{
myRenderer->setSelectedIndex(0);
myTIAZoom->setValue(300);
myTIAInterpolate->setState(false);
myVSizeAdjust->setValue(0);
mySpeed->setValue(0);
// screen size
myFullscreen->setState(false);
//myFullScreenMode->setSelectedIndex(0);
myUseStretch->setState(false);
myTVOverscan->setValue(0);
myTIAZoom->setValue(300);
myVSizeAdjust->setValue(0);
// speed
mySpeed->setValue(0);
myUseVSync->setState(true);
// misc
myUIMessages->setState(true);
myFastSCBios->setState(true);
myUseThreads->setState(false);
handlePaletteChange();
handleFullScreenChange();
break;
}
case 1: // Palettes
myTIAPalette->setSelected("standard", "");
myPhaseShiftNtsc->setValue(262);
myPhaseShiftPal->setValue(313);
myPhaseShiftNtsc->setValue(PaletteHandler::DEF_NTSC_SHIFT * 10);
myPhaseShiftPal->setValue(PaletteHandler::DEF_PAL_SHIFT * 10);
myTVHue->setValue(50);
myTVSatur->setValue(50);
myTVContrast->setValue(50);
myTVBright->setValue(50);
myTVGamma->setValue(50);
handlePaletteChange();
break;
case 2: // TV effects
@ -685,6 +690,27 @@ void VideoDialog::handlePaletteChange()
myPhaseShiftPal->setEnabled(enable);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VideoDialog::handlePaletteUpdate()
{
// TIA Palette
instance().settings().setValue("palette",
myTIAPalette->getSelectedTag().toString());
// Palette adjustables
PaletteHandler::Adjustable paletteAdj;
paletteAdj.phaseNtsc = myPhaseShiftNtsc->getValue();
paletteAdj.phasePal = myPhaseShiftPal->getValue();
paletteAdj.hue = myTVHue->getValue();
paletteAdj.saturation = myTVSatur->getValue();
paletteAdj.contrast = myTVContrast->getValue();
paletteAdj.brightness = myTVBright->getValue();
paletteAdj.gamma = myTVGamma->getValue();
instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(paletteAdj);
if(instance().hasConsole())
instance().frameBuffer().tiaSurface().paletteHandler().setPalette();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VideoDialog::handleFullScreenChange()
{
@ -722,12 +748,24 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd,
close();
break;
case GuiObject::kCloseCmd:
// restore palette settings
instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(myPaletteAdj);
instance().frameBuffer().tiaSurface().paletteHandler().setPalette(myPalette);
Dialog::handleCommand(sender, cmd, data, 0);
break;
case GuiObject::kDefaultsCmd:
setDefaults();
break;
case kPaletteChanged:
handlePaletteChange();
handlePaletteUpdate();
break;
case kPaletteUpdated:
handlePaletteUpdate();
break;
case kNtscShiftChanged:
@ -737,6 +775,7 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd,
ss << std::setw(4) << std::fixed << std::setprecision(1)
<< (0.1 * abs(myPhaseShiftNtsc->getValue())) << DEGREE;
myPhaseShiftNtsc->setValueLabel(ss.str());
handlePaletteUpdate();
break;
}
case kPalShiftChanged:
@ -746,6 +785,7 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd,
ss << std::setw(4) << std::fixed << std::setprecision(1)
<< (0.1 * abs(myPhaseShiftPal->getValue())) << DEGREE;
myPhaseShiftPal->setValueLabel(ss.str());
handlePaletteUpdate();
break;
}
case kVSizeChanged:
@ -818,3 +858,57 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd,
break;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VideoDialog::addPalette(int x, int y, int w, int h)
{
if(instance().hasConsole())
{
constexpr int NUM_LUMA = 8;
constexpr int NUM_CHROMA = 16;
const GUI::Font& ifont = instance().frameBuffer().infoFont();
const int lwidth = ifont.getMaxCharWidth() * 1.5;
const float COLW = float(w - lwidth) / NUM_LUMA;
const float COLH = float(h) / NUM_CHROMA;
const int yofs = (COLH - ifont.getFontHeight() + 1) / 2;
for(int idx = 0; idx < NUM_CHROMA; ++idx)
{
myColorLbl[idx] = new StaticTextWidget(myTab, ifont, x, y + yofs + idx * COLH, " ");
for(int lum = 0; lum < NUM_LUMA; ++lum)
{
myColor[idx][lum] = new ColorWidget(myTab, _font, x + lwidth + lum * COLW, y + idx * COLH,
COLW + 1, COLH + 1, 0, false);
}
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VideoDialog::colorPalette()
{
if(instance().hasConsole())
{
constexpr int NUM_LUMA = 8;
constexpr int NUM_CHROMA = 16;
const int order[2][NUM_CHROMA] =
{
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{0, 1, 2, 4, 6, 8, 10, 12, 13, 11, 9, 7, 5, 3, 14, 15}
};
const int type = instance().console().timing() == ConsoleTiming::pal ? 1 : 0;
for(int idx = 0; idx < NUM_CHROMA; ++idx)
{
ostringstream ss;
const int color = order[type][idx];
ss << Common::Base::HEX1 << std::uppercase << color;
myColorLbl[idx]->setLabel(ss.str());
for(int lum = 0; lum < NUM_LUMA; ++lum)
{
myColor[idx][lum]->setColor(color * NUM_CHROMA + lum * 2); // skip grayscale colors
}
}
}
}

View File

@ -20,6 +20,7 @@
class CommandSender;
class CheckboxWidget;
class ColorWidget;
class DialogContainer;
class PopUpWidget;
class RadioButtonGroup;
@ -29,6 +30,7 @@ class TabWidget;
class OSystem;
#include "Dialog.hxx"
#include "PaletteHandler.hxx"
#include "NTSCFilter.hxx"
#include "bspf.hxx"
@ -50,10 +52,13 @@ class VideoDialog : public Dialog
void handleTVModeChange(NTSCFilter::Preset);
void loadTVAdjustables(NTSCFilter::Preset preset);
void handlePaletteChange();
void handlePaletteUpdate();
void handleFullScreenChange();
void handleOverscanChange();
void handlePhosphorChange();
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void addPalette(int x, int y, int h, int w);
void colorPalette();
private:
TabWidget* myTab;
@ -77,6 +82,9 @@ class VideoDialog : public Dialog
CheckboxWidget* myUIMessages{nullptr};
CheckboxWidget* myFastSCBios{nullptr};
CheckboxWidget* myUseThreads{nullptr};
std::array<StaticTextWidget*, 16> myColorLbl{nullptr};
//std::array<ColorWidget*, 16> myColor{nullptr};
ColorWidget* myColor[16][8]{nullptr};
// TV effects adjustables (custom mode)
PopUpWidget* myTVMode{nullptr};
@ -106,10 +114,14 @@ class VideoDialog : public Dialog
ButtonWidget* myCloneBad{nullptr};
ButtonWidget* myCloneCustom{nullptr};
string myPalette;
PaletteHandler::Adjustable myPaletteAdj{0.0F};
enum {
kPaletteChanged = 'VDpl',
kNtscShiftChanged = 'VDns',
kPalShiftChanged = 'VDps',
kPaletteUpdated = 'VDpu',
kSpeedupChanged = 'VDSp',
kVSizeChanged = 'VDVs',
kFullScreenChanged = 'VDFs',