added color parameters to 'Custom' palette, fixes #657

This commit is contained in:
thrust26 2020-10-31 19:06:58 +01:00
parent e92b9f3b94
commit ec52ea8049
12 changed files with 438 additions and 98 deletions

View File

@ -16,14 +16,16 @@
* Added basic (entire and single line only) text cut/copy and paste. * Added basic (entire and single line only) text cut/copy and paste.
* Fixed bug with aspect correction and fullscreen mode; snapshots from * Added color parameters to 'Custom' palette
such a mode are now pixel-exact.
* Some improvements to AVox-USB adaptor functionality: * Some improvements to AVox-USB adaptor functionality:
- Made serial port used for an AtariVox-USB adaptor editable. - Made serial port used for an AtariVox-USB adaptor editable.
- Autodetection of serial ports no longer messes up devices plugged - Autodetection of serial ports no longer messes up devices plugged
into other serial ports. into other serial ports.
* Fixed bug with aspect correction and fullscreen mode; snapshots from
such a mode are now pixel-exact.
* Fixed crash with missing or incorrectly sized SaveKey data file, and * Fixed crash with missing or incorrectly sized SaveKey data file, and
with certain functions not working (erase pages, erase entire EEPROM). with certain functions not working (erase pages, erase entire EEPROM).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -2130,7 +2130,7 @@
<td><pre>-palette &lt;standard|z26|user|custom&gt;</pre></td> <td><pre>-palette &lt;standard|z26|user|custom&gt;</pre></td>
<td>Set the palette to either normal Stella, the one used in the z26 <td>Set the palette to either normal Stella, the one used in the z26
emulator, a user-defined palette, or a custom palette generated emulator, a user-defined palette, or a custom palette generated
from user-defined phase shifts.</td> from user-defined parameters.</td>
</tr> </tr>
<tr> <tr>
@ -2143,6 +2143,36 @@
<td>Adjust phase shift of 'custom' PAL palette.</td> <td>Adjust phase shift of 'custom' PAL palette.</td>
</tr> </tr>
<tr>
<td><pre>-pal.red_scale &lt;number&gt;</pre></td>
<td>Adjust red scale of 'custom' palette (range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-pal.red_shift &lt;number&gt;</pre></td>
<td>Adjust red shift of 'custom' palette (range -22.5 to 22.5).</td>
</tr>
<tr>
<td><pre>-pal.green_scale &lt;number&gt;</pre></td>
<td>Adjust green scale of 'custom' palette (range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-pal.green_shift &lt;number&gt;</pre></td>
<td>Adjust green shift of 'custom' palette (range -22.5 to 22.5).</td>
</tr>
<tr>
<td><pre>-pal.blue_scale &lt;number&gt;</pre></td>
<td>Adjust blue scale of 'custom' palette (range -1.0 to 1.0).</td>
</tr>
<tr>
<td><pre>-pal.blue_shift &lt;number&gt;</pre></td>
<td>Adjust blue shift of 'custom' palette (range -22.5 to 22.5).</td>
</tr>
<tr> <tr>
<td><pre>-pal.hue &lt;number&gt;</pre></td> <td><pre>-pal.hue &lt;number&gt;</pre></td>
<td>Adjust hue of current palette (range -1.0 to 1.0).</td> <td>Adjust hue of current palette (range -1.0 to 1.0).</td>
@ -3078,8 +3108,11 @@
<table border="1" cellpadding="4"> <table border="1" cellpadding="4">
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">Command Line</a></th></tr> <tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">Command Line</a></th></tr>
<tr><td>Palette</td><td>Palette used for emulation mode</td><td>-palette</td></tr> <tr><td>Palette</td><td>Palette used for emulation mode</td><td>-palette</td></tr>
<tr><td>NTSC phase</td><td>Adjust phase shift for 'Custom' NTSC palette</td><td>-pal.phase_ntsc</td></tr> <tr><td>NTSC phase</td><td>Adjust phase shift of 'Custom' NTSC palette</td><td>-pal.phase_ntsc</td></tr>
<tr><td>PAL phase</td><td>Adjust phase shift for 'Custom' PAL palette</td><td>-pal.phase_pal</td></tr> <tr><td>PAL phase</td><td>Adjust phase shift of 'Custom' PAL palette</td><td>-pal.phase_pal</td></tr>
<tr><td>R</td><td>Adjust red scale and shift of 'Custom' palette</td><td>-pal.red_scale, -pal.red_shift</td></tr>
<tr><td>G</td><td>Adjust green scale and shift of 'Custom' palette</td><td>-pal.green_scale, -pal.green_shift</td></tr>
<tr><td>B</td><td>Adjust blue scale and shift of 'Custom' palette</td><td>-pal.blue_scale, -pal.blue_shift</td></tr>
<tr><td>Hue</td><td>Adjust hue of currently selected palette</td><td>-pal.hue</td></tr> <tr><td>Hue</td><td>Adjust hue of currently selected palette</td><td>-pal.hue</td></tr>
<tr><td>Saturation</td><td>Adjust saturation of currently selected palette</td><td>-pal.saturation</td></tr> <tr><td>Saturation</td><td>Adjust saturation of currently selected palette</td><td>-pal.saturation</td></tr>
<tr><td>Contrast</td><td>Adjust contrast of currently selected palette</td><td>-pal.contrast</td></tr> <tr><td>Contrast</td><td>Adjust contrast of currently selected palette</td><td>-pal.contrast</td></tr>

View File

@ -74,14 +74,38 @@ void PaletteHandler::cyclePalette(int direction)
setPalette(palette); setPalette(palette);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PaletteHandler::isCustomAdjustable() const
{
return myCurrentAdjustable >= CUSTOM_START
&& myCurrentAdjustable <= CUSTOM_END;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PaletteHandler::isPhaseShift() const
{
return myCurrentAdjustable == PHASE_SHIFT;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PaletteHandler::isRGBScale() const
{
return myCurrentAdjustable >= RED_SCALE && myCurrentAdjustable <= BLUE_SCALE;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PaletteHandler::isRGBShift() const
{
return myCurrentAdjustable >= RED_SHIFT && myCurrentAdjustable <= BLUE_SHIFT;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::showAdjustableMessage() void PaletteHandler::showAdjustableMessage()
{ {
const bool isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr;
ostringstream msg, buf; ostringstream msg, buf;
msg << "Palette " << myAdjustables[myCurrentAdjustable].name; msg << "Palette " << myAdjustables[myCurrentAdjustable].name;
if(isPhaseShift) if(isPhaseShift())
{ {
const ConsoleTiming timing = myOSystem.console().timing(); const ConsoleTiming timing = myOSystem.console().timing();
const bool isNTSC = timing == ConsoleTiming::ntsc; const bool isNTSC = timing == ConsoleTiming::ntsc;
@ -90,12 +114,22 @@ void PaletteHandler::showAdjustableMessage()
buf << std::fixed << std::setprecision(1) << value << DEGREE; buf << std::fixed << std::setprecision(1) << value << DEGREE;
myOSystem.frameBuffer().showMessage( myOSystem.frameBuffer().showMessage(
"Palette phase shift", buf.str(), value, "Palette phase shift", buf.str(), value,
(isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) - MAX_SHIFT, (isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) - MAX_PHASE_SHIFT,
(isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) + MAX_SHIFT); (isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) + MAX_PHASE_SHIFT);
}
else if(isRGBShift())
{
const float value = *myAdjustables[myCurrentAdjustable].value;
buf << std::fixed << std::setprecision(1) << value << DEGREE;
myOSystem.frameBuffer().showMessage(
msg.str(), buf.str(), value, -MAX_RGB_SHIFT, +MAX_RGB_SHIFT);
} }
else else
{ {
const int value = scaleTo100(*myAdjustables[myCurrentAdjustable].value); const int value = isRGBScale()
? scaleRGBTo100(*myAdjustables[myCurrentAdjustable].value)
: scaleTo100(*myAdjustables[myCurrentAdjustable].value);
buf << value << "%"; buf << value << "%";
myOSystem.frameBuffer().showMessage( myOSystem.frameBuffer().showMessage(
msg.str(), buf.str(), value); msg.str(), buf.str(), value);
@ -106,15 +140,15 @@ void PaletteHandler::showAdjustableMessage()
void PaletteHandler::cycleAdjustable(int direction) void PaletteHandler::cycleAdjustable(int direction)
{ {
const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette"); const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette");
bool isPhaseShift; bool isCustomAdj;
do { do {
myCurrentAdjustable = BSPF::clampw(int(myCurrentAdjustable + direction), 0, NUM_ADJUSTABLES - 1); myCurrentAdjustable = BSPF::clampw(int(myCurrentAdjustable + direction), 0, NUM_ADJUSTABLES - 1);
isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr; isCustomAdj = isCustomAdjustable();
// skip phase shift when 'Custom' palette is not selected // skip phase shift when 'Custom' palette is not selected
if(!direction && isPhaseShift && !isCustomPalette) if(!direction && isCustomAdj && !isCustomPalette)
myCurrentAdjustable++; myCurrentAdjustable++;
} while(isPhaseShift && !isCustomPalette); } while(isCustomAdj && !isCustomPalette);
showAdjustableMessage(); showAdjustableMessage();
} }
@ -122,29 +156,38 @@ void PaletteHandler::cycleAdjustable(int direction)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::changeAdjustable(int adjustable, int direction) void PaletteHandler::changeAdjustable(int adjustable, int direction)
{ {
const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette");
const bool isPhaseShift = myAdjustables[adjustable].value == nullptr;
myCurrentAdjustable = adjustable; myCurrentAdjustable = adjustable;
if(isPhaseShift && !isCustomPalette)
myCurrentAdjustable++;
changeCurrentAdjustable(direction); changeCurrentAdjustable(direction);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::changeCurrentAdjustable(int direction) void PaletteHandler::changeCurrentAdjustable(int direction)
{ {
if(myAdjustables[myCurrentAdjustable].value == nullptr) if(isPhaseShift())
changeColorPhaseShift(direction); changeColorPhaseShift(direction);
else else
{ {
int newVal = scaleTo100(*myAdjustables[myCurrentAdjustable].value); if(isRGBScale())
{
int newVal = scaleRGBTo100(*myAdjustables[myCurrentAdjustable].value);
newVal = BSPF::clamp(newVal + direction * 1, 0, 100); newVal = BSPF::clamp(newVal + direction * 1, 0, 100);
*myAdjustables[myCurrentAdjustable].value = scaleRGBFrom100(newVal);
}
else if(isRGBShift())
{
float newShift = *myAdjustables[myCurrentAdjustable].value;
*myAdjustables[myCurrentAdjustable].value = scaleFrom100(newVal); newShift = BSPF::clamp(newShift + direction * 0.5F, -MAX_RGB_SHIFT, MAX_RGB_SHIFT);
*myAdjustables[myCurrentAdjustable].value = newShift;
}
else
{
int newVal = scaleTo100(*myAdjustables[myCurrentAdjustable].value);
newVal = BSPF::clamp(newVal + direction * 1, 0, 100);
*myAdjustables[myCurrentAdjustable].value = scaleFrom100(newVal);
}
showAdjustableMessage(); showAdjustableMessage();
setPalette(); setPalette();
} }
@ -162,7 +205,7 @@ void PaletteHandler::changeColorPhaseShift(int direction)
const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT; const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT;
float newPhase = isNTSC ? myPhaseNTSC : myPhasePAL; float newPhase = isNTSC ? myPhaseNTSC : myPhasePAL;
newPhase = BSPF::clamp(newPhase + direction * 0.3F, shift - MAX_SHIFT, shift + MAX_SHIFT); newPhase = BSPF::clamp(newPhase + direction * 0.3F, shift - MAX_PHASE_SHIFT, shift + MAX_PHASE_SHIFT);
if(isNTSC) if(isNTSC)
myPhaseNTSC = newPhase; myPhaseNTSC = newPhase;
@ -181,15 +224,21 @@ void PaletteHandler::loadConfig(const Settings& settings)
{ {
// Load adjustables // Load adjustables
myPhaseNTSC = BSPF::clamp(settings.getFloat("pal.phase_ntsc"), myPhaseNTSC = BSPF::clamp(settings.getFloat("pal.phase_ntsc"),
DEF_NTSC_SHIFT - MAX_SHIFT, DEF_NTSC_SHIFT + MAX_SHIFT); DEF_NTSC_SHIFT - MAX_PHASE_SHIFT, DEF_NTSC_SHIFT + MAX_PHASE_SHIFT);
myPhasePAL = BSPF::clamp(settings.getFloat("pal.phase_pal"), myPhasePAL = BSPF::clamp(settings.getFloat("pal.phase_pal"),
DEF_PAL_SHIFT - MAX_SHIFT, DEF_PAL_SHIFT + MAX_SHIFT); DEF_PAL_SHIFT - MAX_PHASE_SHIFT, DEF_PAL_SHIFT + MAX_PHASE_SHIFT);
myRedScale = BSPF::clamp(settings.getFloat("pal.red_scale"), -1.0F, 1.0F) + 1.F;
myGreenScale = BSPF::clamp(settings.getFloat("pal.green_scale"), -1.0F, 1.0F) + 1.F;
myBlueScale = BSPF::clamp(settings.getFloat("pal.blue_scale"), -1.0F, 1.0F) + 1.F;
myRedShift = BSPF::clamp(settings.getFloat("pal.red_shift"), -MAX_RGB_SHIFT, MAX_RGB_SHIFT);
myGreenShift = BSPF::clamp(settings.getFloat("pal.green_shift"), -MAX_RGB_SHIFT, MAX_RGB_SHIFT);
myBlueShift = BSPF::clamp(settings.getFloat("pal.blue_shift"), -MAX_RGB_SHIFT, MAX_RGB_SHIFT);
myHue = BSPF::clamp(settings.getFloat("pal.hue"), -1.0F, 1.0F); myHue = BSPF::clamp(settings.getFloat("pal.hue"), -1.0F, 1.0F);
mySaturation = BSPF::clamp(settings.getFloat("pal.saturation"), -1.0F, 1.0F); mySaturation = BSPF::clamp(settings.getFloat("pal.saturation"), -1.0F, 1.0F);
myContrast = BSPF::clamp(settings.getFloat("pal.contrast"), -1.0F, 1.0F); myContrast = BSPF::clamp(settings.getFloat("pal.contrast"), -1.0F, 1.0F);
myBrightness = BSPF::clamp(settings.getFloat("pal.brightness"), -1.0F, 1.0F); myBrightness = BSPF::clamp(settings.getFloat("pal.brightness"), -1.0F, 1.0F);
myGamma = BSPF::clamp(settings.getFloat("pal.gamma"), -1.0F, 1.0F); myGamma = BSPF::clamp(settings.getFloat("pal.gamma"), -1.0F, 1.0F);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -198,6 +247,12 @@ void PaletteHandler::saveConfig(Settings& settings) const
// Save adjustables // Save adjustables
settings.setValue("pal.phase_ntsc", myPhaseNTSC); settings.setValue("pal.phase_ntsc", myPhaseNTSC);
settings.setValue("pal.phase_pal", myPhasePAL); settings.setValue("pal.phase_pal", myPhasePAL);
settings.setValue("pal.red_scale", myRedScale - 1.F);
settings.setValue("pal.green_scale", myGreenScale - 1.F);
settings.setValue("pal.blue_scale", myBlueScale - 1.F);
settings.setValue("pal.red_shift", myRedShift);
settings.setValue("pal.green_shift", myGreenShift);
settings.setValue("pal.blue_shift", myBlueShift);
settings.setValue("pal.hue", myHue); settings.setValue("pal.hue", myHue);
settings.setValue("pal.saturation", mySaturation); settings.setValue("pal.saturation", mySaturation);
@ -209,8 +264,14 @@ void PaletteHandler::saveConfig(Settings& settings) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::setAdjustables(const Adjustable& adjustable) void PaletteHandler::setAdjustables(const Adjustable& adjustable)
{ {
myPhaseNTSC = adjustable.phaseNtsc / 10.F; myPhaseNTSC = scaleFromAngles(adjustable.phaseNtsc);
myPhasePAL = adjustable.phasePal / 10.F; myPhasePAL = scaleFromAngles(adjustable.phasePal);
myRedScale = scaleRGBFrom100(adjustable.redScale);
myGreenScale = scaleRGBFrom100(adjustable.greenScale);
myBlueScale = scaleRGBFrom100(adjustable.blueScale);
myRedShift = scaleFromAngles(adjustable.redShift);
myGreenShift = scaleFromAngles(adjustable.greenShift);
myBlueShift = scaleFromAngles(adjustable.blueShift);
myHue = scaleFrom100(adjustable.hue); myHue = scaleFrom100(adjustable.hue);
mySaturation = scaleFrom100(adjustable.saturation); mySaturation = scaleFrom100(adjustable.saturation);
@ -222,8 +283,14 @@ void PaletteHandler::setAdjustables(const Adjustable& adjustable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PaletteHandler::getAdjustables(Adjustable& adjustable) const void PaletteHandler::getAdjustables(Adjustable& adjustable) const
{ {
adjustable.phaseNtsc = myPhaseNTSC * 10.F; adjustable.phaseNtsc = scaleToAngles(myPhaseNTSC);
adjustable.phasePal = myPhasePAL * 10.F; adjustable.phasePal = scaleToAngles(myPhasePAL);
adjustable.redScale = scaleRGBTo100(myRedScale);
adjustable.greenScale = scaleRGBTo100(myGreenScale);
adjustable.blueScale = scaleRGBTo100(myBlueScale);
adjustable.redShift = scaleToAngles(myRedShift);
adjustable.greenShift = scaleToAngles(myGreenShift);
adjustable.blueShift = scaleToAngles(myBlueShift);
adjustable.hue = scaleTo100(myHue); adjustable.hue = scaleTo100(myHue);
adjustable.saturation = scaleTo100(mySaturation); adjustable.saturation = scaleTo100(mySaturation);
@ -371,10 +438,9 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
constexpr int NUM_LUMA = 8; constexpr int NUM_LUMA = 8;
constexpr float SATURATION = 0.25F; // default saturation constexpr float SATURATION = 0.25F; // default saturation
float color[NUM_CHROMA][2] = {{0.0F}};
if(timing == ConsoleTiming::ntsc) if(timing == ConsoleTiming::ntsc)
{ {
vector2d IQ[NUM_CHROMA];
// YIQ is YUV shifted by 33° // YIQ is YUV shifted by 33°
constexpr float offset = 33 * BSPF::PI_f / 180; constexpr float offset = 33 * BSPF::PI_f / 180;
const float shift = myPhaseNTSC * BSPF::PI_f / 180; const float shift = myPhaseNTSC * BSPF::PI_f / 180;
@ -382,22 +448,23 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
// color 0 is grayscale // color 0 is grayscale
for(int chroma = 1; chroma < NUM_CHROMA; chroma++) for(int chroma = 1; chroma < NUM_CHROMA; chroma++)
{ {
color[chroma][0] = SATURATION * sinf(offset + shift * (chroma - 1)); IQ[chroma] = vector2d(SATURATION * sinf(offset + shift * (chroma - 1)),
color[chroma][1] = SATURATION * cosf(offset + shift * (chroma - 1) - BSPF::PI_f); SATURATION * cosf(offset + shift * (chroma - 1) - BSPF::PI_f));
} }
const vector2d IQR = scale(rotate(vector2d(+0.956F, +0.621F), myRedShift), myRedScale);
const vector2d IQG = scale(rotate(vector2d(-0.272F, -0.647F), myGreenShift), myGreenScale);
const vector2d IQB = scale(rotate(vector2d(-1.106F, +1.703F), myBlueShift), myBlueScale);
for(int chroma = 0; chroma < NUM_CHROMA; chroma++) for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
{ {
const float I = color[chroma][0];
const float Q = color[chroma][1];
for(int luma = 0; luma < NUM_LUMA; luma++) for(int luma = 0; luma < NUM_LUMA; luma++)
{ {
const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90 const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
float R = Y + 0.956F * I + 0.621F * Q; float R = Y + dotProduct(IQ[chroma], IQR);
float G = Y - 0.272F * I - 0.647F * Q; float G = Y + dotProduct(IQ[chroma], IQG);
float B = Y - 1.106F * I + 1.703F * Q; float B = Y + dotProduct(IQ[chroma], IQB);
if(R < 0) R = 0; if(R < 0) R = 0;
if(G < 0) G = 0; if(G < 0) G = 0;
@ -420,35 +487,37 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
constexpr float offset = BSPF::PI_f; constexpr float offset = BSPF::PI_f;
const float shift = myPhasePAL * BSPF::PI_f / 180; const float shift = myPhasePAL * BSPF::PI_f / 180;
constexpr float fixedShift = 22.5F * BSPF::PI_f / 180; constexpr float fixedShift = 22.5F * BSPF::PI_f / 180;
vector2d UV[NUM_CHROMA];
// colors 0, 1, 14 and 15 are grayscale // colors 0, 1, 14 and 15 are grayscale
for(int chroma = 2; chroma < NUM_CHROMA - 2; chroma++) for(int chroma = 2; chroma < NUM_CHROMA - 2; chroma++)
{ {
int idx = NUM_CHROMA - 1 - chroma; int idx = NUM_CHROMA - 1 - chroma;
color[idx][0] = SATURATION * sinf(offset - fixedShift * chroma);
UV[idx].x = SATURATION * sinf(offset - fixedShift * chroma);
if ((idx & 1) == 0) if ((idx & 1) == 0)
color[idx][1] = SATURATION * sinf(offset - shift * (chroma - 3.5F) / 2.F); UV[idx].y = SATURATION * sinf(offset - shift * (chroma - 3.5F) / 2.F);
else else
color[idx][1] = SATURATION * -sinf(offset - shift * chroma / 2.F); UV[idx].y = SATURATION * -sinf(offset - shift * chroma / 2.F);
} }
// Most sources
const vector2d UVR = scale(rotate(vector2d( 0.000F, +1.403F), myRedShift), myRedScale);
const vector2d UVG = scale(rotate(vector2d(-0.344F, -0.714F), myGreenShift), myGreenScale);
const vector2d UVB = scale(rotate(vector2d(+0.714F, 0.000F), myBlueShift), myBlueScale);
// German Wikipedia, huh???
//float R = Y + 1 / 0.877 * V;
//float B = Y + 1 / 0.493 * U;
//float G = 1.704 * Y - 0.590 * R - 0.194 * B;
for(int chroma = 0; chroma < NUM_CHROMA; chroma++) for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
{ {
const float U = color[chroma][0];
const float V = color[chroma][1];
for(int luma = 0; luma < NUM_LUMA; luma++) for(int luma = 0; luma < NUM_LUMA; luma++)
{ {
const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90 const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
// Most sources float R = Y + dotProduct(UV[chroma], UVR);
float R = Y + 1.403F * V; float G = Y + dotProduct(UV[chroma], UVG);
float G = Y - 0.344F * U - 0.714F * V; float B = Y + dotProduct(UV[chroma], UVB);
float B = Y + 1.770F * U;
// German Wikipedia, huh???
//float B = Y + 1 / 0.493 * U;
//float R = Y + 1 / 0.877 * V;
//float G = 1.704 * Y - 0.590 * R - 0.194 * B;
if(R < 0) R = 0.0; if(R < 0) R = 0.0;
if(G < 0) G = 0.0; if(G < 0) G = 0.0;
@ -491,6 +560,28 @@ void PaletteHandler::adjustHueSaturation(int& R, int& G, int& B, float H, float
B = BSPF::clamp(b, 0.F, 255.F); B = BSPF::clamp(b, 0.F, 255.F);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteHandler::vector2d PaletteHandler::rotate(const PaletteHandler::vector2d& vec, float angle) const
{
const float r = angle * BSPF::PI_f / 180;
return PaletteHandler::vector2d(vec.x * cosf(r) - vec.y * sinf(r),
vec.x * sinf(r) + vec.y * cosf(r));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PaletteHandler::vector2d PaletteHandler::scale(const PaletteHandler::vector2d& vec, float factor) const
{
return PaletteHandler::vector2d(vec.x * factor, vec.y * factor);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
float PaletteHandler::dotProduct(const PaletteHandler::vector2d& vec1,
const PaletteHandler::vector2d& vec2) const
{
return vec1.x * vec2.x + vec1.y * vec2.y;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const PaletteArray PaletteHandler::ourNTSCPalette = { const PaletteArray PaletteHandler::ourNTSCPalette = {
0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0, 0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,

View File

@ -35,20 +35,32 @@ class PaletteHandler
// Phase shift default and limits // Phase shift default and limits
static constexpr float DEF_NTSC_SHIFT = 26.2F; static constexpr float DEF_NTSC_SHIFT = 26.2F;
static constexpr float DEF_PAL_SHIFT = 31.3F; // ~= 360 / 11.5 static constexpr float DEF_PAL_SHIFT = 31.3F; // ~= 360 / 11.5
static constexpr float MAX_SHIFT = 4.5F; static constexpr float MAX_PHASE_SHIFT = 4.5F;
static constexpr float DEF_RGB_SHIFT = 0.0F;
static constexpr float MAX_RGB_SHIFT = 22.5F;
enum Adjustables { enum Adjustables {
PHASE_SHIFT, PHASE_SHIFT,
RED_SCALE,
GREEN_SCALE,
BLUE_SCALE,
RED_SHIFT,
GREEN_SHIFT,
BLUE_SHIFT,
HUE, HUE,
SATURATION, SATURATION,
CONTRAST, CONTRAST,
BRIGHTNESS, BRIGHTNESS,
GAMMA GAMMA,
CUSTOM_START = PHASE_SHIFT,
CUSTOM_END = BLUE_SHIFT,
}; };
// Externally used adjustment parameters // Externally used adjustment parameters
struct Adjustable { struct Adjustable {
float phaseNtsc{0.F}, phasePal{0.F}; float phaseNtsc{0.F}, phasePal{0.F},
redScale{0.F}, greenScale{0.F}, blueScale{0.F},
redShift{0.F}, greenShift{0.F}, blueShift{0.F};
uInt32 hue{0}, saturation{0}, contrast{0}, brightness{0}, gamma{0}; uInt32 hue{0}, saturation{0}, contrast{0}, brightness{0}, gamma{0};
}; };
@ -108,6 +120,7 @@ class PaletteHandler
*/ */
void setPalette(); void setPalette();
private: private:
static constexpr char DEGREE = 0x1c; static constexpr char DEGREE = 0x1c;
@ -121,12 +134,45 @@ class PaletteHandler
MaxType = Custom MaxType = Custom
}; };
struct vector2d {
float x;
float y;
explicit vector2d()
: x(0.F), y(0.F) { }
explicit vector2d(float _x, float _y)
: x(_x), y(_y) { }
};
/**
Convert RGB adjustables from/to 100% scale
*/
static constexpr float scaleRGBFrom100(float x) { return x / 50.F; }
static constexpr uInt32 scaleRGBTo100(float x) { return uInt32(50.0001F * (x - 0.F)); }
/**
Convert angles
*/
static constexpr float scaleFromAngles(float x) { return x / 10.F; }
static constexpr Int32 scaleToAngles(float x) { return uInt32(10.F * x); }
/** /**
Convert adjustables from/to 100% scale Convert adjustables from/to 100% scale
*/ */
static constexpr float scaleFrom100(float x) { return (x / 50.F) - 1.F; } static constexpr float scaleFrom100(float x) { return (x / 50.F) - 1.F; }
static constexpr uInt32 scaleTo100(float x) { return uInt32(50.0001F * (x + 1.F)); } static constexpr uInt32 scaleTo100(float x) { return uInt32(50.0001F * (x + 1.F)); }
/**
Check for 'Custom' palette only adjustables
*/
bool isCustomAdjustable() const;
bool isPhaseShift() const;
bool isRGBScale() const;
bool isRGBShift() const;
/** /**
Convert palette settings name to enumeration. Convert palette settings name to enumeration.
@ -186,6 +232,21 @@ class PaletteHandler
*/ */
void adjustHueSaturation(int& R, int& G, int& B, float H, float S); void adjustHueSaturation(int& R, int& G, int& B, float H, float S);
/**
Rotate a 2D vector.
*/
vector2d rotate(const vector2d& vec, float angle) const;
/**
Scale a 2D vector.
*/
vector2d scale(const vector2d& vec, float factor) const;
/**
Get the dot product of two 2D vectors.
*/
float dotProduct(const vector2d& vec1, const vector2d& vec2) const;
/** /**
Loads a user-defined palette file (from OSystem::paletteFile), filling the Loads a user-defined palette file (from OSystem::paletteFile), filling the
appropriate user-defined palette arrays. appropriate user-defined palette arrays.
@ -193,7 +254,7 @@ class PaletteHandler
void loadUserPalette(); void loadUserPalette();
private: private:
static constexpr int NUM_ADJUSTABLES = 6; static constexpr int NUM_ADJUSTABLES = 12;
OSystem& myOSystem; OSystem& myOSystem;
@ -207,6 +268,12 @@ class PaletteHandler
const std::array<AdjustableTag, NUM_ADJUSTABLES> myAdjustables = const std::array<AdjustableTag, NUM_ADJUSTABLES> myAdjustables =
{ { { {
{ "phase shift", nullptr }, { "phase shift", nullptr },
{ "red scale", &myRedScale },
{ "green scale", &myGreenScale },
{ "blue scale", &myBlueScale },
{ "red shift", &myRedShift },
{ "green shift", &myGreenShift },
{ "blue shift", &myBlueShift },
{ "hue", &myHue }, { "hue", &myHue },
{ "saturation", &mySaturation }, { "saturation", &mySaturation },
{ "contrast", &myContrast }, { "contrast", &myContrast },
@ -217,6 +284,14 @@ class PaletteHandler
// NTSC and PAL color phase shifts // NTSC and PAL color phase shifts
float myPhaseNTSC{DEF_NTSC_SHIFT}; float myPhaseNTSC{DEF_NTSC_SHIFT};
float myPhasePAL{DEF_PAL_SHIFT}; float myPhasePAL{DEF_PAL_SHIFT};
// Color intensities
float myRedScale{1.0F};
float myGreenScale{1.0F};
float myBlueScale{1.0F};
// Color shifts
float myRedShift{0.0F};
float myGreenShift{0.0F};
float myBlueShift{0.0F};
// range -1.0 to +1.0 (as in AtariNTSC) // range -1.0 to +1.0 (as in AtariNTSC)
// Basic parameters // Basic parameters
float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees

View File

@ -377,7 +377,9 @@ AdjustFunction EventHandler::cycleAdjustSetting(int direction)
#ifdef ADAPTABLE_REFRESH_SUPPORT #ifdef ADAPTABLE_REFRESH_SUPPORT
|| (myAdjustSetting == AdjustSetting::ADAPT_REFRESH && !isFullScreen) || (myAdjustSetting == AdjustSetting::ADAPT_REFRESH && !isFullScreen)
#endif #endif
|| (myAdjustSetting == AdjustSetting::PALETTE_PHASE && !isCustomPalette) || (myAdjustSetting >= AdjustSetting::PALETTE_PHASE
&& myAdjustSetting <= AdjustSetting::PALETTE_BLUE_SHIFT
&& !isCustomPalette)
|| (myAdjustSetting >= AdjustSetting::NTSC_SHARPNESS || (myAdjustSetting >= AdjustSetting::NTSC_SHARPNESS
&& myAdjustSetting <= AdjustSetting::NTSC_BLEEDING && myAdjustSetting <= AdjustSetting::NTSC_BLEEDING
&& !isCustomFilter); && !isCustomFilter);
@ -425,6 +427,18 @@ AdjustFunction EventHandler::getAdjustSetting(AdjustSetting setting)
std::bind(&PaletteHandler::cyclePalette, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), _1), std::bind(&PaletteHandler::cyclePalette, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::PHASE_SHIFT, _1), PaletteHandler::PHASE_SHIFT, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::RED_SCALE, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::RED_SHIFT, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::GREEN_SCALE, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::GREEN_SHIFT, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::BLUE_SCALE, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::BLUE_SHIFT, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
PaletteHandler::HUE, _1), PaletteHandler::HUE, _1),
std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),

View File

@ -431,6 +431,12 @@ class EventHandler
// Palette adjustables // Palette adjustables
PALETTE, PALETTE,
PALETTE_PHASE, PALETTE_PHASE,
PALETTE_RED_SCALE,
PALETTE_RED_SHIFT,
PALETTE_GREEN_SCALE,
PALETTE_GREEN_SHIFT,
PALETTE_BLUE_SCALE,
PALETTE_BLUE_SHIFT,
PALETTE_HUE, PALETTE_HUE,
PALETTE_SATURATION, PALETTE_SATURATION,
PALETTE_CONTRAST, PALETTE_CONTRAST,

View File

@ -81,6 +81,7 @@ void PointingDevice::update()
return; return;
// Update horizontal direction // Update horizontal direction
cerr << myEvent.get(Event::MouseAxisXMove) << ", " << myHCounterRemainder << endl;
updateDirection( myEvent.get(Event::MouseAxisXMove), myHCounterRemainder, updateDirection( myEvent.get(Event::MouseAxisXMove), myHCounterRemainder,
myTrackBallLeft, myTrackBallLinesH, myScanCountH, myFirstScanOffsetH); myTrackBallLeft, myTrackBallLinesH, myScanCountH, myFirstScanOffsetH);

View File

@ -62,6 +62,13 @@ Settings::Settings()
setPermanent("palette", PaletteHandler::SETTING_STANDARD); setPermanent("palette", PaletteHandler::SETTING_STANDARD);
setPermanent("pal.phase_ntsc", "26.2"); setPermanent("pal.phase_ntsc", "26.2");
setPermanent("pal.phase_pal", "31.3"); setPermanent("pal.phase_pal", "31.3");
setPermanent("pal.red_scale", "0.0");
setPermanent("pal.green_scale", "0.0");
setPermanent("pal.blue_scale", "0.0");
setPermanent("pal.red_shift", "0.0");
setPermanent("pal.green_shift", "0.0");
setPermanent("pal.blue_shift", "0.0");
setPermanent("pal.contrast", "0.0"); setPermanent("pal.contrast", "0.0");
setPermanent("pal.brightness", "0.0"); setPermanent("pal.brightness", "0.0");
setPermanent("pal.hue", "0.0"); setPermanent("pal.hue", "0.0");
@ -415,16 +422,24 @@ void Settings::usage() const
<< " -center <1|0> Centers game window in windowed modes\n" << " -center <1|0> Centers game window in windowed modes\n"
<< " -windowedpos <XxY> Sets the window position in windowed emulator mode\n" << " -windowedpos <XxY> Sets the window position in windowed emulator mode\n"
<< " -display <number> Sets the display for Stella's emulator\n" << " -display <number> Sets the display for Stella's emulator\n"
<< " -palette <standard| Use the specified color palette\n" << endl
<< " z26|user|\n" << " -palette <standard| Use the specified color palette\n"
<< " custom>\n" << " z26|user|\n"
<< " -pal.phase_ntsc <number> Phase shift for NTSC 'custom' palette\n" << " custom>\n"
<< " -pal.phase_pal <number> Phase shift for PAL 'custom' palette\n" << " -pal.phase_ntsc <number> Phase shift for NTSC 'custom' palette\n"
<< " -pal.hue <-1.0 - 1.0> Adjust hue for current palette\n" << " -pal.phase_pal <number> Phase shift for PAL 'custom' palette\n"
<< " -pal.saturation <-1.0 - 1.0> Adjust saturation of current palette\n" << " -pal.red_scale <-1.0 - 1.0> Adjust red scale for 'custom' palette\n"
<< " -pal.contrast <-1.0 - 1.0> Adjust contrast of current palette\n" << " -pal.red_shift <-1.0 - 1.0> Adjust red shift for 'custom' palette\n"
<< " -pal.brightness <-1.0 - 1.0> Adjust brightness of current palette\n" << " -pal.green_scale <-1.0 - 1.0> Adjust green scale for 'custom' palette\n"
<< " -pal.gamma <-1.0 - 1.0> Adjust gamma of current palette\n" << " -pal.green_shift <-1.0 - 1.0> Adjust green shift for 'custom' palette\n"
<< " -pal.blue_scale <-1.0 - 1.0> Adjust blue scale for 'custom' palette\n"
<< " -pal.blue_shift <-1.0 - 1.0> Adjust blue shift for 'custom' palette\n"
<< " -pal.hue <-1.0 - 1.0> Adjust hue for current palette\n"
<< " -pal.saturation <-1.0 - 1.0> Adjust saturation of current palette\n"
<< " -pal.contrast <-1.0 - 1.0> Adjust contrast of current palette\n"
<< " -pal.brightness <-1.0 - 1.0> Adjust brightness of current palette\n"
<< " -pal.gamma <-1.0 - 1.0> Adjust gamma of current palette\n"
<< endl
<< " -speed <number> Run emulation at the given speed\n" << " -speed <number> Run emulation at the given speed\n"
<< " -turbo <1|0> Enable 'Turbo' mode for maximum emulation speed\n" << " -turbo <1|0> Enable 'Turbo' mode for maximum emulation speed\n"
<< " -uimessages <1|0> Show onscreen UI messages for different events\n" << " -uimessages <1|0> Show onscreen UI messages for different events\n"

View File

@ -223,25 +223,82 @@ void VideoAudioDialog::addPaletteTab()
const int swidth = myTIAPalette->getWidth() - lwidth; const int swidth = myTIAPalette->getWidth() - lwidth;
const int plWidth = _font.getStringWidth("NTSC phase "); const int plWidth = _font.getStringWidth("NTSC phase ");
const int pswidth = swidth - INDENT + lwidth - plWidth; const int pswidth = swidth - INDENT + lwidth - plWidth;
xpos += INDENT;
myPhaseShiftNtsc = myPhaseShiftNtsc =
new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight, new SliderWidget(myTab, _font, xpos, ypos - 1, pswidth, lineHeight,
"NTSC phase", plWidth, kNtscShiftChanged, fontWidth * 5); "NTSC phase", plWidth, kNtscShiftChanged, fontWidth * 5);
myPhaseShiftNtsc->setMinValue((PaletteHandler::DEF_NTSC_SHIFT - PaletteHandler::MAX_SHIFT) * 10); myPhaseShiftNtsc->setMinValue((PaletteHandler::DEF_NTSC_SHIFT - PaletteHandler::MAX_PHASE_SHIFT) * 10);
myPhaseShiftNtsc->setMaxValue((PaletteHandler::DEF_NTSC_SHIFT + PaletteHandler::MAX_SHIFT) * 10); myPhaseShiftNtsc->setMaxValue((PaletteHandler::DEF_NTSC_SHIFT + PaletteHandler::MAX_PHASE_SHIFT) * 10);
myPhaseShiftNtsc->setTickmarkIntervals(4); myPhaseShiftNtsc->setTickmarkIntervals(4);
wid.push_back(myPhaseShiftNtsc); wid.push_back(myPhaseShiftNtsc);
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
myPhaseShiftPal = myPhaseShiftPal =
new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight, new SliderWidget(myTab, _font, xpos, ypos - 1, pswidth, lineHeight,
"PAL phase", plWidth, kPalShiftChanged, fontWidth * 5); "PAL phase", plWidth, kPalShiftChanged, fontWidth * 5);
myPhaseShiftPal->setMinValue((PaletteHandler::DEF_PAL_SHIFT - PaletteHandler::MAX_SHIFT) * 10); myPhaseShiftPal->setMinValue((PaletteHandler::DEF_PAL_SHIFT - PaletteHandler::MAX_PHASE_SHIFT) * 10);
myPhaseShiftPal->setMaxValue((PaletteHandler::DEF_PAL_SHIFT + PaletteHandler::MAX_SHIFT) * 10); myPhaseShiftPal->setMaxValue((PaletteHandler::DEF_PAL_SHIFT + PaletteHandler::MAX_PHASE_SHIFT) * 10);
myPhaseShiftPal->setTickmarkIntervals(4); myPhaseShiftPal->setTickmarkIntervals(4);
wid.push_back(myPhaseShiftPal); wid.push_back(myPhaseShiftPal);
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
const int rgblWidth = _font.getStringWidth("R ");
const int rgbsWidth = (myTIAPalette->getWidth() - INDENT - rgblWidth - fontWidth * 5) / 2;
myTVRedScale =
new SliderWidget(myTab, _font, xpos, ypos - 1, rgbsWidth, lineHeight,
"R", rgblWidth, kPaletteUpdated, fontWidth * 4, "%");
myTVRedScale->setMinValue(0);
myTVRedScale->setMaxValue(100);
myTVRedScale->setTickmarkIntervals(2);
wid.push_back(myTVRedScale);
const int xposr = myTIAPalette->getRight() - rgbsWidth;
myTVRedShift =
new SliderWidget(myTab, _font, xposr, ypos - 1, rgbsWidth, lineHeight,
"", 0, kRedShiftChanged, fontWidth * 6);
myTVRedShift->setMinValue((PaletteHandler::DEF_RGB_SHIFT - PaletteHandler::MAX_RGB_SHIFT) * 10);
myTVRedShift->setMaxValue((PaletteHandler::DEF_RGB_SHIFT + PaletteHandler::MAX_RGB_SHIFT) * 10);
myTVRedShift->setTickmarkIntervals(2);
wid.push_back(myTVRedShift);
ypos += lineHeight + VGAP;
myTVGreenScale =
new SliderWidget(myTab, _font, xpos, ypos - 1, rgbsWidth, lineHeight,
"G", rgblWidth, kPaletteUpdated, fontWidth * 4, "%");
myTVGreenScale->setMinValue(0);
myTVGreenScale->setMaxValue(100);
myTVGreenScale->setTickmarkIntervals(2);
wid.push_back(myTVGreenScale);
myTVGreenShift =
new SliderWidget(myTab, _font, xposr, ypos - 1, rgbsWidth, lineHeight,
"", 0, kGreenShiftChanged, fontWidth * 6);
myTVGreenShift->setMinValue((PaletteHandler::DEF_RGB_SHIFT - PaletteHandler::MAX_RGB_SHIFT) * 10);
myTVGreenShift->setMaxValue((PaletteHandler::DEF_RGB_SHIFT + PaletteHandler::MAX_RGB_SHIFT) * 10);
myTVGreenShift->setTickmarkIntervals(2);
wid.push_back(myTVGreenShift);
ypos += lineHeight + VGAP;
myTVBlueScale =
new SliderWidget(myTab, _font, xpos, ypos - 1, rgbsWidth, lineHeight,
"B", rgblWidth, kPaletteUpdated, fontWidth * 4, "%");
myTVBlueScale->setMinValue(0);
myTVBlueScale->setMaxValue(100);
myTVBlueScale->setTickmarkIntervals(2);
wid.push_back(myTVBlueScale);
myTVBlueShift =
new SliderWidget(myTab, _font, xposr, ypos - 1, rgbsWidth, lineHeight,
"", 0, kBlueShiftChanged, fontWidth * 6);
myTVBlueShift->setMinValue((PaletteHandler::DEF_RGB_SHIFT - PaletteHandler::MAX_RGB_SHIFT) * 10);
myTVBlueShift->setMaxValue((PaletteHandler::DEF_RGB_SHIFT + PaletteHandler::MAX_RGB_SHIFT) * 10);
myTVBlueShift->setTickmarkIntervals(2);
wid.push_back(myTVBlueShift);
ypos += lineHeight + VGAP;
xpos -= INDENT;
CREATE_CUSTOM_SLIDERS(Hue, "Hue ", kPaletteUpdated) CREATE_CUSTOM_SLIDERS(Hue, "Hue ", kPaletteUpdated)
CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", kPaletteUpdated) CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", kPaletteUpdated)
CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", kPaletteUpdated) CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", kPaletteUpdated)
@ -524,6 +581,12 @@ void VideoAudioDialog::loadConfig()
instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(myPaletteAdj); instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(myPaletteAdj);
myPhaseShiftNtsc->setValue(myPaletteAdj.phaseNtsc); myPhaseShiftNtsc->setValue(myPaletteAdj.phaseNtsc);
myPhaseShiftPal->setValue(myPaletteAdj.phasePal); myPhaseShiftPal->setValue(myPaletteAdj.phasePal);
myTVRedScale->setValue(myPaletteAdj.redScale);
myTVRedShift->setValue(myPaletteAdj.redShift);
myTVGreenScale->setValue(myPaletteAdj.greenScale);
myTVGreenShift->setValue(myPaletteAdj.greenShift);
myTVBlueScale->setValue(myPaletteAdj.blueScale);
myTVBlueShift->setValue(myPaletteAdj.blueShift);
myTVHue->setValue(myPaletteAdj.hue); myTVHue->setValue(myPaletteAdj.hue);
myTVBright->setValue(myPaletteAdj.brightness); myTVBright->setValue(myPaletteAdj.brightness);
myTVContrast->setValue(myPaletteAdj.contrast); myTVContrast->setValue(myPaletteAdj.contrast);
@ -760,6 +823,12 @@ void VideoAudioDialog::setDefaults()
myTIAPalette->setSelected(PaletteHandler::SETTING_STANDARD); myTIAPalette->setSelected(PaletteHandler::SETTING_STANDARD);
myPhaseShiftNtsc->setValue(PaletteHandler::DEF_NTSC_SHIFT * 10); myPhaseShiftNtsc->setValue(PaletteHandler::DEF_NTSC_SHIFT * 10);
myPhaseShiftPal->setValue(PaletteHandler::DEF_PAL_SHIFT * 10); myPhaseShiftPal->setValue(PaletteHandler::DEF_PAL_SHIFT * 10);
myTVRedScale->setValue(50);
myTVRedShift->setValue(PaletteHandler::DEF_RGB_SHIFT);
myTVGreenScale->setValue(50);
myTVGreenShift->setValue(PaletteHandler::DEF_RGB_SHIFT);
myTVBlueScale->setValue(50);
myTVBlueShift->setValue(PaletteHandler::DEF_RGB_SHIFT);
myTVHue->setValue(50); myTVHue->setValue(50);
myTVSatur->setValue(50); myTVSatur->setValue(50);
myTVContrast->setValue(50); myTVContrast->setValue(50);
@ -847,6 +916,23 @@ void VideoAudioDialog::handlePaletteChange()
myPhaseShiftNtsc->setEnabled(enable); myPhaseShiftNtsc->setEnabled(enable);
myPhaseShiftPal->setEnabled(enable); myPhaseShiftPal->setEnabled(enable);
myTVRedScale->setEnabled(enable);
myTVRedShift->setEnabled(enable);
myTVGreenScale->setEnabled(enable);
myTVGreenShift->setEnabled(enable);
myTVBlueScale->setEnabled(enable);
myTVBlueShift->setEnabled(enable);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VideoAudioDialog::handleShiftChanged(SliderWidget* widget)
{
std::ostringstream ss;
ss << std::setw(4) << std::fixed << std::setprecision(1)
<< (0.1 * (widget->getValue())) << DEGREE;
widget->setValueLabel(ss.str());
handlePaletteUpdate();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -859,6 +945,12 @@ void VideoAudioDialog::handlePaletteUpdate()
PaletteHandler::Adjustable paletteAdj; PaletteHandler::Adjustable paletteAdj;
paletteAdj.phaseNtsc = myPhaseShiftNtsc->getValue(); paletteAdj.phaseNtsc = myPhaseShiftNtsc->getValue();
paletteAdj.phasePal = myPhaseShiftPal->getValue(); paletteAdj.phasePal = myPhaseShiftPal->getValue();
paletteAdj.redScale = myTVRedScale->getValue();
paletteAdj.redShift = myTVRedShift->getValue();
paletteAdj.greenScale = myTVGreenScale->getValue();
paletteAdj.greenShift = myTVGreenShift->getValue();
paletteAdj.blueScale = myTVBlueScale->getValue();
paletteAdj.blueShift = myTVBlueShift->getValue();
paletteAdj.hue = myTVHue->getValue(); paletteAdj.hue = myTVHue->getValue();
paletteAdj.saturation = myTVSatur->getValue(); paletteAdj.saturation = myTVSatur->getValue();
paletteAdj.contrast = myTVContrast->getValue(); paletteAdj.contrast = myTVContrast->getValue();
@ -931,25 +1023,25 @@ void VideoAudioDialog::handleCommand(CommandSender* sender, int cmd,
break; break;
case kNtscShiftChanged: case kNtscShiftChanged:
{ handleShiftChanged(myPhaseShiftNtsc);
std::ostringstream ss;
ss << std::setw(4) << std::fixed << std::setprecision(1)
<< (0.1 * abs(myPhaseShiftNtsc->getValue())) << DEGREE;
myPhaseShiftNtsc->setValueLabel(ss.str());
handlePaletteUpdate();
break; break;
}
case kPalShiftChanged: case kPalShiftChanged:
{ handleShiftChanged(myPhaseShiftPal);
std::ostringstream ss;
ss << std::setw(4) << std::fixed << std::setprecision(1)
<< (0.1 * abs(myPhaseShiftPal->getValue())) << DEGREE;
myPhaseShiftPal->setValueLabel(ss.str());
handlePaletteUpdate();
break; break;
}
case kRedShiftChanged:
handleShiftChanged(myTVRedShift);
break;
case kGreenShiftChanged:
handleShiftChanged(myTVGreenShift);
break;
case kBlueShiftChanged:
handleShiftChanged(myTVBlueShift);
break;
case kVSizeChanged: case kVSizeChanged:
{ {
int adjust = myVSizeAdjust->getValue(); int adjust = myVSizeAdjust->getValue();

View File

@ -53,6 +53,7 @@ class VideoAudioDialog : public Dialog
void handleTVModeChange(NTSCFilter::Preset); void handleTVModeChange(NTSCFilter::Preset);
void loadTVAdjustables(NTSCFilter::Preset preset); void loadTVAdjustables(NTSCFilter::Preset preset);
void handlePaletteChange(); void handlePaletteChange();
void handleShiftChanged(SliderWidget* widget);
void handlePaletteUpdate(); void handlePaletteUpdate();
void handleFullScreenChange(); void handleFullScreenChange();
void handleOverscanChange(); void handleOverscanChange();
@ -105,6 +106,12 @@ class VideoAudioDialog : public Dialog
PopUpWidget* myTIAPalette{nullptr}; PopUpWidget* myTIAPalette{nullptr};
SliderWidget* myPhaseShiftNtsc{nullptr}; SliderWidget* myPhaseShiftNtsc{nullptr};
SliderWidget* myPhaseShiftPal{nullptr}; SliderWidget* myPhaseShiftPal{nullptr};
SliderWidget* myTVRedScale{nullptr};
SliderWidget* myTVRedShift{nullptr};
SliderWidget* myTVGreenScale{nullptr};
SliderWidget* myTVGreenShift{nullptr};
SliderWidget* myTVBlueScale{nullptr};
SliderWidget* myTVBlueShift{nullptr};
SliderWidget* myTVHue{nullptr}; SliderWidget* myTVHue{nullptr};
SliderWidget* myTVSatur{nullptr}; SliderWidget* myTVSatur{nullptr};
SliderWidget* myTVBright{nullptr}; SliderWidget* myTVBright{nullptr};
@ -138,6 +145,9 @@ class VideoAudioDialog : public Dialog
kPaletteChanged = 'VDpl', kPaletteChanged = 'VDpl',
kNtscShiftChanged = 'VDns', kNtscShiftChanged = 'VDns',
kPalShiftChanged = 'VDps', kPalShiftChanged = 'VDps',
kRedShiftChanged = 'VDrs',
kGreenShiftChanged = 'VDgs',
kBlueShiftChanged = 'VDbs',
kPaletteUpdated = 'VDpu', kPaletteUpdated = 'VDpu',
kTVModeChanged = 'VDtv', kTVModeChanged = 'VDtv',

View File

@ -47,8 +47,9 @@ WhatsNewDialog::WhatsNewDialog(OSystem& osystem, DialogContainer& parent, const
add(ypos, "fixed bug with launcher not remembering last selected ROM"); add(ypos, "fixed bug with launcher not remembering last selected ROM");
#else #else
add(ypos, "added basic text cut/copy/paste to UI"); add(ypos, "added basic text cut/copy/paste to UI");
add(ypos, "fixed fullscreen mode, aspect correction and pixel-exact snapshots"); add(ypos, "added color parameters to 'Custom' palette");
add(ypos, "improved AVox-USB adaptor autodetection"); add(ypos, "improved AVox-USB adaptor autodetection");
add(ypos, "fixed fullscreen mode, aspect correction and pixel-exact snapshots");
add(ypos, "fixed crash with SaveKey ROMs (EEPROM file issues)"); add(ypos, "fixed crash with SaveKey ROMs (EEPROM file issues)");
add(ypos, "fixed bug with launcher not remembering last selected ROM"); add(ypos, "fixed bug with launcher not remembering last selected ROM");
add(ypos, ELLIPSIS + " (for a complete list see 'docs/Changes.txt')"); add(ypos, ELLIPSIS + " (for a complete list see 'docs/Changes.txt')");