diff --git a/Changes.txt b/Changes.txt index f0c1b4acc..222b1e8a3 100644 --- a/Changes.txt +++ b/Changes.txt @@ -22,6 +22,8 @@ a game. This allows the user to save high scores for these games. For each game and variation, the top 10 scores can be saved. (TODO: Doc) + * Added interactive palette to Video & Audio settings + * Added 'Custom' palette, generated from user controlled phase shifts. * Added 'Turbo' mode, runs the game as fast as the computer allows. diff --git a/src/common/KeyMap.hxx b/src/common/KeyMap.hxx index 94d3b4242..0b7eff2fe 100644 --- a/src/common/KeyMap.hxx +++ b/src/common/KeyMap.hxx @@ -21,6 +21,7 @@ #include #include "Event.hxx" #include "EventHandlerConstants.hxx" +#include "StellaKeys.hxx" /** This class handles keyboard mappings in Stella. diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx index f32600345..9384d3232 100644 --- a/src/common/PKeyboardHandler.cxx +++ b/src/common/PKeyboardHandler.cxx @@ -17,13 +17,7 @@ #include "OSystem.hxx" #include "Console.hxx" -#include "Settings.hxx" #include "EventHandler.hxx" -#include "Sound.hxx" -#include "StateManager.hxx" -#include "StellaKeys.hxx" -#include "TIASurface.hxx" -#include "PNGLibrary.hxx" #include "PKeyboardHandler.hxx" #ifdef DEBUGGER_SUPPORT @@ -475,25 +469,30 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo {Event::ToggleFullScreen, KBDK_RETURN, MOD3}, {Event::OverscanDecrease, KBDK_PAGEDOWN, KBDM_SHIFT}, {Event::OverscanIncrease, KBDK_PAGEUP, KBDM_SHIFT}, - {Event::VidmodeStd, KBDK_1, MOD3}, - {Event::VidmodeRGB, KBDK_2, MOD3}, - {Event::VidmodeSVideo, KBDK_3, MOD3}, - {Event::VidModeComposite, KBDK_4, MOD3}, - {Event::VidModeBad, KBDK_5, MOD3}, - {Event::VidModeCustom, KBDK_6, MOD3}, - {Event::PreviousAttribute, KBDK_7, KBDM_SHIFT | MOD3}, - {Event::NextAttribute, KBDK_7, MOD3}, - {Event::DecreaseAttribute, KBDK_8, KBDM_SHIFT | MOD3}, - {Event::IncreaseAttribute, KBDK_8, MOD3}, + //{Event::VidmodeStd, KBDK_1, MOD3}, + //{Event::VidmodeRGB, KBDK_2, MOD3}, + //{Event::VidmodeSVideo, KBDK_3, MOD3}, + //{Event::VidModeComposite, KBDK_4, MOD3}, + //{Event::VidModeBad, KBDK_5, MOD3}, + //{Event::VidModeCustom, KBDK_6, MOD3}, + {Event::PreviousVideoMode, KBDK_1, KBDM_SHIFT | MOD3}, + {Event::NextVideoMode, KBDK_1, MOD3}, + {Event::PreviousAttribute, KBDK_2, KBDM_SHIFT | MOD3}, + {Event::NextAttribute, KBDK_2, MOD3}, + {Event::DecreaseAttribute, KBDK_3, KBDM_SHIFT | MOD3}, + {Event::IncreaseAttribute, KBDK_3, MOD3}, + {Event::PreviousPaletteAttribute, KBDK_4, KBDM_SHIFT | MOD3}, + {Event::NextPaletteAttribute, KBDK_4, MOD3}, + {Event::PaletteAttributeDecrease, KBDK_5, KBDM_SHIFT | MOD3}, + {Event::PaletteAttributeIncrease, KBDK_5, MOD3}, {Event::PhosphorDecrease, KBDK_9, KBDM_SHIFT | MOD3}, {Event::PhosphorIncrease, KBDK_9, MOD3}, {Event::TogglePhosphor, KBDK_P, MOD3}, {Event::ScanlinesDecrease, KBDK_0, KBDM_SHIFT | MOD3}, {Event::ScanlinesIncrease, KBDK_0, MOD3}, {Event::ToggleColorLoss, KBDK_L, KBDM_CTRL}, - {Event::TogglePalette, KBDK_P, KBDM_CTRL}, - {Event::ColorShiftDecrease, KBDK_9, KBDM_SHIFT | KBDM_CTRL}, - {Event::ColorShiftIncrease, KBDK_9, KBDM_CTRL}, + {Event::PaletteDecrease, KBDK_P, KBDM_SHIFT | KBDM_CTRL}, + {Event::PaletteIncrease, KBDK_P, KBDM_CTRL}, {Event::ToggleInter, KBDK_I, KBDM_CTRL}, {Event::ToggleTurbo, KBDK_T, KBDM_CTRL}, {Event::ToggleJitter, KBDK_J, MOD3}, diff --git a/src/common/PaletteHandler.cxx b/src/common/PaletteHandler.cxx new file mode 100644 index 000000000..2aecc6abf --- /dev/null +++ b/src/common/PaletteHandler.cxx @@ -0,0 +1,738 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include + +#include "Console.hxx" +#include "FrameBuffer.hxx" + +#include "PaletteHandler.hxx" + +PaletteHandler::PaletteHandler(OSystem& system) + : myOSystem(system) +{ + // Load user-defined palette for this ROM + loadUserPalette(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteHandler::PaletteType PaletteHandler::toPaletteType(const string& name) const +{ + if(name == SETTING_Z26) + return PaletteType::Z26; + + if(name == SETTING_USER && myUserPaletteDefined) + return PaletteType::User; + + if(name == SETTING_CUSTOM) + return PaletteType::Custom; + + return PaletteType::Standard; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string PaletteHandler::toPaletteName(PaletteType type) const +{ + const string SETTING_NAMES[int(PaletteType::NumTypes)] = { + SETTING_STANDARD, SETTING_Z26, SETTING_USER, SETTING_CUSTOM + }; + + return SETTING_NAMES[type]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::cyclePalette(bool next) +{ + const string MESSAGES[PaletteType::NumTypes] = { + "Standard Stella", "Z26", "User-defined", "Custom" + }; + int type = toPaletteType(myOSystem.settings().getString("palette")); + + if(next) + { + if(type == PaletteType::MaxType) + type = PaletteType::Standard; + else + type++; + // If we have no user-defined palette, we will skip it + if(type == PaletteType::User && !myUserPaletteDefined) + type++; + } + else + { + if(type == PaletteType::MinType) + type = PaletteType::MaxType; + else + type--; + // If we have no user-defined palette, we will skip it + if(type == PaletteType::User && !myUserPaletteDefined) + type--; + } + + const string palette = toPaletteName(PaletteType(type)); + const string message = MESSAGES[type] + " palette"; + + myOSystem.frameBuffer().showMessage(message); + + setPalette(palette); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::cycleAdjustable(bool next) +{ + const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette"); + bool isPhaseShift; + + do { + if(next) + { + myCurrentAdjustable++; + myCurrentAdjustable %= NUM_ADJUSTABLES; + } + else + { + if(myCurrentAdjustable == 0) + myCurrentAdjustable = NUM_ADJUSTABLES - 1; + else + myCurrentAdjustable--; + } + isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr; + + // skip phase shift when 'Custom' palette is not selected + } while(isPhaseShift && !isCustomPalette); + + ostringstream buf; + buf << "Palette adjustable '" << myAdjustables[myCurrentAdjustable].name + << "' selected ("; + if(isPhaseShift) + buf << (myOSystem.console().timing() == ConsoleTiming::pal ? myPhasePAL : myPhaseNTSC) + << DEGREE << ")"; + else + buf << scaleTo100(*myAdjustables[myCurrentAdjustable].value) << "%)"; + + myOSystem.frameBuffer().showMessage(buf.str()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::changeAdjustable(bool increase) +{ + if(myAdjustables[myCurrentAdjustable].value == nullptr) + changeColorPhaseShift(increase); + else + { + int newVal = scaleTo100(*myAdjustables[myCurrentAdjustable].value); + + if(increase) + newVal += 2; // += 2% + else + newVal -= 2; // -= 2% + newVal = BSPF::clamp(newVal, 0, 100); + + *myAdjustables[myCurrentAdjustable].value = scaleFrom100(newVal); + + ostringstream buf; + buf << "Custom '" << myAdjustables[myCurrentAdjustable].name + << "' set to " << newVal << "%"; + + myOSystem.frameBuffer().showMessage(buf.str()); + setPalette(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::changeColorPhaseShift(bool increase) +{ + const ConsoleTiming timing = myOSystem.console().timing(); + + // SECAM is not supported + if(timing != ConsoleTiming::secam) + { + const bool isNTSC = timing == ConsoleTiming::ntsc; + const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT; + float newPhase = isNTSC ? myPhaseNTSC : myPhasePAL; + + if(increase) // increase color phase shift + newPhase += 0.3F; + else // decrease color phase shift + newPhase -= 0.3F; + newPhase = BSPF::clamp(newPhase, shift - MAX_SHIFT, shift + MAX_SHIFT); + + if(isNTSC) + myPhaseNTSC = newPhase; + else + myPhasePAL = newPhase; + + generateCustomPalette(timing); + setPalette(SETTING_CUSTOM); + + ostringstream ss; + ss << "Color phase shift at " + << std::fixed << std::setprecision(1) << newPhase << 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); + myBrightness = BSPF::clamp(settings.getFloat("tv.brightness"), -1.0F, 1.0F); + myGamma = BSPF::clamp(settings.getFloat("tv.gamma"), -1.0F, 1.0F); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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); + settings.setValue("tv.brightness", myBrightness); + settings.setValue("tv.gamma", myGamma); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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); + myBrightness = scaleFrom100(adjustable.brightness); + myGamma = scaleFrom100(adjustable.gamma); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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); + adjustable.brightness = scaleTo100(myBrightness); + adjustable.gamma = scaleTo100(myGamma); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::setPalette(const string& name) +{ + myOSystem.settings().setValue("palette", name); + + setPalette(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::setPalette() +{ + if(myOSystem.hasConsole()) + { + const string& name = myOSystem.settings().getString("palette"); + + // Look at all the palettes, since we don't know which one is + // currently active + static constexpr BSPF::array2D palettes = {{ + { &ourNTSCPalette, &ourPALPalette, &ourSECAMPalette }, + { &ourNTSCPaletteZ26, &ourPALPaletteZ26, &ourSECAMPaletteZ26 }, + { &ourUserNTSCPalette, &ourUserPALPalette, &ourUserSECAMPalette }, + { &ourCustomNTSCPalette, &ourCustomPALPalette, &ourSECAMPalette } + }}; + // See which format we should be using + const ConsoleTiming timing = myOSystem.console().timing(); + const PaletteType paletteType = toPaletteType(name); + // Now consider the current display format + const PaletteArray* palette = palettes[paletteType][int(timing)]; + + if(paletteType == PaletteType::Custom) + generateCustomPalette(timing); + + myOSystem.frameBuffer().setTIAPalette(adjustedPalette(*palette)); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::adjustedPalette(const PaletteArray& palette) +{ + PaletteArray destPalette; + // Constants for saturation and gray scale calculation + constexpr float PR = .2989F; + constexpr float PG = .5870F; + constexpr float PB = .1140F; + // Generate adjust table + constexpr int ADJUST_SIZE = 256; + constexpr int RGB_UNIT = 1 << 8; + constexpr float RGB_OFFSET = 0.5F; + const float hue = myHue; + 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 */ + constexpr float toFloat = 1.F / (ADJUST_SIZE - 1); + std::array adjust; + + for(int i = 0; i < ADJUST_SIZE; i++) + adjust[i] = powf(i * toFloat, gamma) * contrast + brightness; + + // Transform original palette into destination palette + for(size_t i = 0; i < destPalette.size(); i += 2) + { + const uInt32 pixel = palette[i]; + int r = (pixel >> 16) & 0xff; + int g = (pixel >> 8) & 0xff; + int b = (pixel >> 0) & 0xff; + + // adjust hue (different for NTSC and PAL?) and saturation + adjustHueSaturation(r, g, b, hue, saturation); + + // adjust contrast, brightness, gamma + r = adjust[r]; + g = adjust[g]; + b = adjust[b]; + + r = BSPF::clamp(r, 0, 255); + g = BSPF::clamp(g, 0, 255); + b = BSPF::clamp(b, 0, 255); + + destPalette[i] = (r << 16) + (g << 8) + b; + + // Fill the odd numbered palette entries with gray values (calculated + // using the standard RGB -> grayscale conversion formula) + // Used for PAL color-loss data and 'greying out' the frame in the debugger. + const uInt8 lum = static_cast((r * PR) + (g * PG) + (b * PB)); + + destPalette[i + 1] = (lum << 16) + (lum << 8) + lum; + } + return destPalette; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::loadUserPalette() +{ + if (!myOSystem.checkUserPalette(true)) + return; + + const string& palette = myOSystem.paletteFile(); + ifstream in(palette, std::ios::binary); + + // Now that we have valid data, create the user-defined palettes + std::array pixbuf; // Temporary buffer for one 24-bit pixel + + for(int i = 0; i < 128; i++) // NTSC palette + { + in.read(reinterpret_cast(pixbuf.data()), 3); + 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(pixbuf.data()), 3); + const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); + ourUserPALPalette[(i<<1)] = pixel; + } + + std::array secam; // All 8 24-bit pixels, plus 8 colorloss pixels + for(int i = 0; i < 8; i++) // SECAM palette + { + in.read(reinterpret_cast(pixbuf.data()), 3); + const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); + secam[(i<<1)] = pixel; + secam[(i<<1)+1] = 0; + } + uInt32* ptr = ourUserSECAMPalette.data(); + for(int i = 0; i < 16; ++i) + { + const uInt32* s = secam.data(); + for(int j = 0; j < 16; ++j) + *ptr++ = *s++; + } + + myUserPaletteDefined = true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::generateCustomPalette(ConsoleTiming timing) +{ + constexpr int NUM_CHROMA = 16; + constexpr int NUM_LUMA = 8; + constexpr float SATURATION = 0.25F; // default saturation + + float color[NUM_CHROMA][2] = {{0.0F}}; + + if(timing == ConsoleTiming::ntsc) + { + // YIQ is YUV shifted by 33° + constexpr float offset = 33 * BSPF::PI_f / 180; + const float shift = myPhaseNTSC * BSPF::PI_f / 180; + + // color 0 is grayscale + for(int chroma = 1; chroma < NUM_CHROMA; chroma++) + { + color[chroma][0] = SATURATION * sinf(offset + shift * (chroma - 1)); + color[chroma][1] = SATURATION * sinf(offset + shift * (chroma - 1 - BSPF::PI_f)); + } + + 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++) + { + const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90 + + float R = Y + 0.956F * I + 0.621F * Q; + float G = Y - 0.272F * I - 0.647F * Q; + float B = Y - 1.106F * I + 1.703F * Q; + + if(R < 0) R = 0; + if(G < 0) G = 0; + if(B < 0) B = 0; + + R = powf(R, 0.9F); + G = powf(G, 0.9F); + B = powf(B, 0.9F); + + int r = BSPF::clamp(R * 255.F, 0.F, 255.F); + int g = BSPF::clamp(G * 255.F, 0.F, 255.F); + int b = BSPF::clamp(B * 255.F, 0.F, 255.F); + + ourCustomNTSCPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b; + } + } + } + else if(timing == ConsoleTiming::pal) + { + constexpr float offset = BSPF::PI_f; + const float shift = myPhasePAL * BSPF::PI_f / 180; + constexpr float fixedShift = 22.5F * BSPF::PI_f / 180; + + // colors 0, 1, 14 and 15 are grayscale + for(int chroma = 2; chroma < NUM_CHROMA - 2; chroma++) + { + int idx = NUM_CHROMA - 1 - chroma; + color[idx][0] = SATURATION * sinf(offset - fixedShift * chroma); + if ((idx & 1) == 0) + color[idx][1] = SATURATION * sinf(offset - shift * (chroma - 3.5F) / 2.F); + else + color[idx][1] = SATURATION * -sinf(offset - shift * chroma / 2.F); + } + + 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++) + { + const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90 + + // 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; + //float G = 1.704 * Y - 0.590 * R - 0.194 * B; + + if(R < 0) R = 0.0; + if(G < 0) G = 0.0; + if(B < 0) B = 0.0; + + R = powf(R, 1.2F); + G = powf(G, 1.2F); + B = powf(B, 1.2F); + + int r = BSPF::clamp(R * 255.F, 0.F, 255.F); + int g = BSPF::clamp(G * 255.F, 0.F, 255.F); + int b = BSPF::clamp(B * 255.F, 0.F, 255.F); + + ourCustomPALPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b; + } + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::adjustHueSaturation(int& R, int& G, int& B, float H, float S) +{ + // Adapted from http://beesbuzz.biz/code/16-hsv-color-transforms + // (C) J. “Fluffy” Shagam + // License: CC BY-SA 4.0 + const float su = S * cosf(-H * BSPF::PI_f); + const float sw = S * sinf(-H * BSPF::PI_f); + const float r = (.299F + .701F * su + .168F * sw) * R + + (.587F - .587F * su + .330F * sw) * G + + (.114F - .114F * su - .497F * sw) * B; + const float g = (.299F - .299F * su - .328F * sw) * R + + (.587F + .413F * su + .035F * sw) * G + + (.114F - .114F * su + .292F * sw) * B; + const float b = (.299F - .300F * su + 1.25F * sw) * R + + (.587F - .588F * su - 1.05F * sw) * G + + (.114F + .886F * su - .203F * sw) * B; + + R = BSPF::clamp(r, 0.F, 255.F); + G = BSPF::clamp(g, 0.F, 255.F); + B = BSPF::clamp(b, 0.F, 255.F); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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, + 0xbbbb35, 0, 0xd2d240, 0, 0xe8e84a, 0, 0xfcfc54, 0, + 0x7c2c00, 0, 0x904811, 0, 0xa26221, 0, 0xb47a30, 0, + 0xc3903d, 0, 0xd2a44a, 0, 0xdfb755, 0, 0xecc860, 0, + 0x901c00, 0, 0xa33915, 0, 0xb55328, 0, 0xc66c3a, 0, + 0xd5824a, 0, 0xe39759, 0, 0xf0aa67, 0, 0xfcbc74, 0, + 0x940000, 0, 0xa71a1a, 0, 0xb83232, 0, 0xc84848, 0, + 0xd65c5c, 0, 0xe46f6f, 0, 0xf08080, 0, 0xfc9090, 0, + 0x840064, 0, 0x97197a, 0, 0xa8308f, 0, 0xb846a2, 0, + 0xc659b3, 0, 0xd46cc3, 0, 0xe07cd2, 0, 0xec8ce0, 0, + 0x500084, 0, 0x68199a, 0, 0x7d30ad, 0, 0x9246c0, 0, + 0xa459d0, 0, 0xb56ce0, 0, 0xc57cee, 0, 0xd48cfc, 0, + 0x140090, 0, 0x331aa3, 0, 0x4e32b5, 0, 0x6848c6, 0, + 0x7f5cd5, 0, 0x956fe3, 0, 0xa980f0, 0, 0xbc90fc, 0, + 0x000094, 0, 0x181aa7, 0, 0x2d32b8, 0, 0x4248c8, 0, + 0x545cd6, 0, 0x656fe4, 0, 0x7580f0, 0, 0x8490fc, 0, + 0x001c88, 0, 0x183b9d, 0, 0x2d57b0, 0, 0x4272c2, 0, + 0x548ad2, 0, 0x65a0e1, 0, 0x75b5ef, 0, 0x84c8fc, 0, + 0x003064, 0, 0x185080, 0, 0x2d6d98, 0, 0x4288b0, 0, + 0x54a0c5, 0, 0x65b7d9, 0, 0x75cceb, 0, 0x84e0fc, 0, + 0x004030, 0, 0x18624e, 0, 0x2d8169, 0, 0x429e82, 0, + 0x54b899, 0, 0x65d1ae, 0, 0x75e7c2, 0, 0x84fcd4, 0, + 0x004400, 0, 0x1a661a, 0, 0x328432, 0, 0x48a048, 0, + 0x5cba5c, 0, 0x6fd26f, 0, 0x80e880, 0, 0x90fc90, 0, + 0x143c00, 0, 0x355f18, 0, 0x527e2d, 0, 0x6e9c42, 0, + 0x87b754, 0, 0x9ed065, 0, 0xb4e775, 0, 0xc8fc84, 0, + 0x303800, 0, 0x505916, 0, 0x6d762b, 0, 0x88923e, 0, + 0xa0ab4f, 0, 0xb7c25f, 0, 0xccd86e, 0, 0xe0ec7c, 0, + 0x482c00, 0, 0x694d14, 0, 0x866a26, 0, 0xa28638, 0, + 0xbb9f47, 0, 0xd2b656, 0, 0xe8cc63, 0, 0xfce070, 0 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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 + 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, + 0x1d0f00, 0, 0x3f2700, 0, 0x614900, 0, 0x836b01, 0, // 1b0 2 + 0xa58d23, 0, 0xc7af45, 0, 0xe9d167, 0, 0xffe789, 0, // was ..0xfff389 + 0x002400, 0, 0x004600, 0, 0x216800, 0, 0x438a07, 0, // 1c8 3 + 0x65ac29, 0, 0x87ce4b, 0, 0xa9f06d, 0, 0xcbff8f, 0, + 0x340000, 0, 0x561400, 0, 0x783602, 0, 0x9a5824, 0, // 1e0 4 + 0xbc7a46, 0, 0xde9c68, 0, 0xffbe8a, 0, 0xffd0ad, 0, // was ..0xffe0ac + 0x002700, 0, 0x004900, 0, 0x0c6b0c, 0, 0x2e8d2e, 0, // 1f8 5 + 0x50af50, 0, 0x72d172, 0, 0x94f394, 0, 0xb6ffb6, 0, + 0x3d0008, 0, 0x610511, 0, 0x832733, 0, 0xa54955, 0, // 210 6 + 0xc76b77, 0, 0xe98d99, 0, 0xffafbb, 0, 0xffd1d7, 0, // was 0x3f0000..0xffd1dd + 0x001e12, 0, 0x004228, 0, 0x046540, 0, 0x268762, 0, // 228 7 + 0x48a984, 0, 0x6acba6, 0, 0x8cedc8, 0, 0xafffe0, 0, // was 0x002100, 0x00431e..0xaeffff + 0x300025, 0, 0x5f0047, 0, 0x811e69, 0, 0xa3408b, 0, // 240 8 + 0xc562ad, 0, 0xe784cf, 0, 0xffa8ea, 0, 0xffc9f2, 0, // was ..0xffa6f1, 0xffc8ff + 0x001431, 0, 0x003653, 0, 0x0a5875, 0, 0x2c7a97, 0, // 258 9 + 0x4e9cb9, 0, 0x70bedb, 0, 0x92e0fd, 0, 0xb4ffff, 0, + 0x2c0052, 0, 0x4e0074, 0, 0x701d96, 0, 0x923fb8, 0, // 270 a + 0xb461da, 0, 0xd683fc, 0, 0xe2a5ff, 0, 0xeec9ff, 0, // was ..0xf8a5ff, 0xffc7ff + 0x001759, 0, 0x00247c, 0, 0x1d469e, 0, 0x3f68c0, 0, // 288 b + 0x618ae2, 0, 0x83acff, 0, 0xa5ceff, 0, 0xc7f0ff, 0, + 0x12006d, 0, 0x34038f, 0, 0x5625b1, 0, 0x7847d3, 0, // 2a0 c + 0x9a69f5, 0, 0xb48cff, 0, 0xc9adff, 0, 0xe1d1ff, 0, // was ..0xbc8bff, 0xdeadff, 0xffcfff, + 0x000070, 0, 0x161292, 0, 0x3834b4, 0, 0x5a56d6, 0, // 2b8 d + 0x7c78f8, 0, 0x9e9aff, 0, 0xc0bcff, 0, 0xe2deff, 0, + 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2d0 e + 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, + 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2e8 f + 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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, + 0x94a414, 0, 0xa8b828, 0, 0xbccc3c, 0, 0xd0e050, 0, + 0x673900, 0, 0x7b4d00, 0, 0x8f6100, 0, 0xa37513, 0, + 0xb78927, 0, 0xcb9d3b, 0, 0xdfb14f, 0, 0xf3c563, 0, + 0x7b2504, 0, 0x8f3918, 0, 0xa34d2c, 0, 0xb76140, 0, + 0xcb7554, 0, 0xdf8968, 0, 0xf39d7c, 0, 0xffb190, 0, + 0x7d122c, 0, 0x912640, 0, 0xa53a54, 0, 0xb94e68, 0, + 0xcd627c, 0, 0xe17690, 0, 0xf58aa4, 0, 0xff9eb8, 0, + 0x730871, 0, 0x871c85, 0, 0x9b3099, 0, 0xaf44ad, 0, + 0xc358c1, 0, 0xd76cd5, 0, 0xeb80e9, 0, 0xff94fd, 0, + 0x5d0b92, 0, 0x711fa6, 0, 0x8533ba, 0, 0x9947ce, 0, + 0xad5be2, 0, 0xc16ff6, 0, 0xd583ff, 0, 0xe997ff, 0, + 0x401599, 0, 0x5429ad, 0, 0x683dc1, 0, 0x7c51d5, 0, + 0x9065e9, 0, 0xa479fd, 0, 0xb88dff, 0, 0xcca1ff, 0, + 0x252593, 0, 0x3939a7, 0, 0x4d4dbb, 0, 0x6161cf, 0, + 0x7575e3, 0, 0x8989f7, 0, 0x9d9dff, 0, 0xb1b1ff, 0, + 0x0f3480, 0, 0x234894, 0, 0x375ca8, 0, 0x4b70bc, 0, + 0x5f84d0, 0, 0x7398e4, 0, 0x87acf8, 0, 0x9bc0ff, 0, + 0x04425a, 0, 0x18566e, 0, 0x2c6a82, 0, 0x407e96, 0, + 0x5492aa, 0, 0x68a6be, 0, 0x7cbad2, 0, 0x90cee6, 0, + 0x044f30, 0, 0x186344, 0, 0x2c7758, 0, 0x408b6c, 0, + 0x549f80, 0, 0x68b394, 0, 0x7cc7a8, 0, 0x90dbbc, 0, + 0x0f550a, 0, 0x23691e, 0, 0x377d32, 0, 0x4b9146, 0, + 0x5fa55a, 0, 0x73b96e, 0, 0x87cd82, 0, 0x9be196, 0, + 0x1f5100, 0, 0x336505, 0, 0x477919, 0, 0x5b8d2d, 0, + 0x6fa141, 0, 0x83b555, 0, 0x97c969, 0, 0xabdd7d, 0, + 0x344600, 0, 0x485a00, 0, 0x5c6e14, 0, 0x708228, 0, + 0x84963c, 0, 0x98aa50, 0, 0xacbe64, 0, 0xc0d278, 0, + 0x463e00, 0, 0x5a5205, 0, 0x6e6619, 0, 0x827a2d, 0, + 0x968e41, 0, 0xaaa255, 0, 0xbeb669, 0, 0xd2ca7d, 0 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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, + 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0, + 0x533a00, 0, 0x674e00, 0, 0x7b6203, 0, 0x8f7617, 0, + 0xa38a2b, 0, 0xb79e3f, 0, 0xcbb253, 0, 0xdfc667, 0, + 0x1b5800, 0, 0x2f6c00, 0, 0x438001, 0, 0x579415, 0, + 0x6ba829, 0, 0x7fbc3d, 0, 0x93d051, 0, 0xa7e465, 0, + 0x6a2900, 0, 0x7e3d12, 0, 0x925126, 0, 0xa6653a, 0, + 0xba794e, 0, 0xce8d62, 0, 0xe2a176, 0, 0xf6b58a, 0, + 0x075b00, 0, 0x1b6f11, 0, 0x2f8325, 0, 0x439739, 0, + 0x57ab4d, 0, 0x6bbf61, 0, 0x7fd375, 0, 0x93e789, 0, + 0x741b2f, 0, 0x882f43, 0, 0x9c4357, 0, 0xb0576b, 0, + 0xc46b7f, 0, 0xd87f93, 0, 0xec93a7, 0, 0xffa7bb, 0, + 0x00572e, 0, 0x106b42, 0, 0x247f56, 0, 0x38936a, 0, + 0x4ca77e, 0, 0x60bb92, 0, 0x74cfa6, 0, 0x88e3ba, 0, + 0x6d165f, 0, 0x812a73, 0, 0x953e87, 0, 0xa9529b, 0, + 0xbd66af, 0, 0xd17ac3, 0, 0xe58ed7, 0, 0xf9a2eb, 0, + 0x014c5e, 0, 0x156072, 0, 0x297486, 0, 0x3d889a, 0, + 0x519cae, 0, 0x65b0c2, 0, 0x79c4d6, 0, 0x8dd8ea, 0, + 0x5f1588, 0, 0x73299c, 0, 0x873db0, 0, 0x9b51c4, 0, + 0xaf65d8, 0, 0xc379ec, 0, 0xd78dff, 0, 0xeba1ff, 0, + 0x123b87, 0, 0x264f9b, 0, 0x3a63af, 0, 0x4e77c3, 0, + 0x628bd7, 0, 0x769feb, 0, 0x8ab3ff, 0, 0x9ec7ff, 0, + 0x451e9d, 0, 0x5932b1, 0, 0x6d46c5, 0, 0x815ad9, 0, + 0x956eed, 0, 0xa982ff, 0, 0xbd96ff, 0, 0xd1aaff, 0, + 0x2a2b9e, 0, 0x3e3fb2, 0, 0x5253c6, 0, 0x6667da, 0, + 0x7a7bee, 0, 0x8e8fff, 0, 0xa2a3ff, 0, 0xb6b7ff, 0, + 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, + 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0, + 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, + 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::ourUserNTSCPalette = { 0 }; // filled from external file + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::ourUserPALPalette = { 0 }; // filled from external file + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::ourUserSECAMPalette = { 0 }; // filled from external file + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::ourCustomNTSCPalette = { 0 }; // filled by function + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::ourCustomPALPalette = { 0 }; // filled by function diff --git a/src/common/PaletteHandler.hxx b/src/common/PaletteHandler.hxx new file mode 100644 index 000000000..3a8c5c9e3 --- /dev/null +++ b/src/common/PaletteHandler.hxx @@ -0,0 +1,238 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef PALETTE_HANDLER_HXX +#define PALETTE_HANDLER_HXX + +#include "bspf.hxx" +#include "OSystem.hxx" +#include "ConsoleTiming.hxx" + +class PaletteHandler +{ + public: + // Setting names of palette types + static constexpr const char* SETTING_STANDARD = "standard"; + static constexpr const char* SETTING_Z26 = "z26"; + static constexpr const char* SETTING_USER = "user"; + static constexpr const char* SETTING_CUSTOM = "custom"; + + // Phase shift default and limits + 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; + + // Externally used adjustment parameters + struct Adjustable { + float phaseNtsc{0.F}, phasePal{0.F}; + uInt32 hue{0}, saturation{0}, contrast{0}, brightness{0}, gamma{0}; + }; + + public: + PaletteHandler(OSystem& system); + virtual ~PaletteHandler() = default; + + /** + Cycle through available palettes. + + @param next Select next palette, else previous one + */ + void cyclePalette(bool next = true); + + /* + Cycle through each palette adjustable. + + @param next Select next adjustable, else previous one + */ + void cycleAdjustable(bool next = true); + + /* + Increase or decrease current palette adjustable. + + @param increase Increase adjustable if true, else decrease + */ + void changeAdjustable(bool increase = true); + + // Load adjustables from settings + void loadConfig(const Settings& settings); + + // Save adjustables to settings + void saveConfig(Settings& settings) const; + + // Set adjustables + void setAdjustables(const Adjustable& adjustable); + + // Retrieve current adjustables + void getAdjustables(Adjustable& adjustable) const; + + /** + Sets the palette according to the given palette name. + + @param name The palette to switch to + */ + void setPalette(const string& name); + + /** + Sets the palette from current settings. + */ + void setPalette(); + + private: + static constexpr char DEGREE = 0x1c; + + enum PaletteType { + Standard, + Z26, + User, + Custom, + NumTypes, + MinType = Standard, + MaxType = Custom + }; + + /** + Convert adjustables from/to 100% scale + */ + constexpr float scaleFrom100(float x) const { return (x / 50.F) - 1.F; } + constexpr uInt32 scaleTo100(float x) const { return uInt32(50 * (x + 1.F)); } + + /** + Convert palette settings name to enumeration. + + @param name The given palette's settings name + + @return The palette type + */ + PaletteType toPaletteType(const string& name) const; + + /** + Convert enumeration to palette settings name. + + @param type The given palette type + + @return The palette's settings name + */ + string toPaletteName(PaletteType type) const; + + /** + Change the "phase shift" variable. + Note that there are two of these (NTSC and PAL). The currently + active mode will determine which one is used. + + @param increase Increase if true, else decrease + */ + void changeColorPhaseShift(bool increase = true); + + /** + Generates a custom palette, based on user defined phase shifts. + + @param timing Use NTSC or PAL phase shift and generate according palette + */ + void generateCustomPalette(ConsoleTiming timing); + + /** + Create new palette by applying palette adjustments on given palette. + + @param source The palette which should be adjusted + + @return An adjusted palette + */ + PaletteArray adjustedPalette(const PaletteArray& source); + + /** + Adjust hue and saturation for given RGB values. + + @param R The red value to adjust + @param G The green value to adjust + @param B The blue value to adjust + @param H The hue adjustment value + @param S The saturation + */ + void adjustHueSaturation(int& R, int& G, int& B, float H, float S); + + /** + Loads a user-defined palette file (from OSystem::paletteFile), filling the + appropriate user-defined palette arrays. + */ + void loadUserPalette(); + + private: + static constexpr int NUM_ADJUSTABLES = 6; + + OSystem& myOSystem; + + // The currently selected adjustable + uInt32 myCurrentAdjustable{0}; + + struct AdjustableTag { + const char* const name{nullptr}; + float* value{nullptr}; + }; + const std::array myAdjustables = + { { + { "phase shift", nullptr }, + { "hue", &myHue }, + { "saturation", &mySaturation }, + { "contrast", &myContrast }, + { "brightness", &myBrightness }, + { "gamma", &myGamma }, + } }; + + // NTSC and PAL color phase shifts + float myPhaseNTSC{DEF_NTSC_SHIFT}; + float myPhasePAL{DEF_PAL_SHIFT}; + // range -1.0 to +1.0 (as in AtariNTSC) + // Basic parameters + 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) + + // Indicates whether an external palette was found and + // successfully loaded + bool myUserPaletteDefined{false}; + + // Table of RGB values for NTSC, PAL and SECAM + static const PaletteArray ourNTSCPalette; + static const PaletteArray ourPALPalette; + static const PaletteArray ourSECAMPalette; + + // Table of RGB values for NTSC, PAL and SECAM - Z26 version + 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; + static PaletteArray ourUserPALPalette; + static PaletteArray ourUserSECAMPalette; + + // Table of RGB values for NTSC, PAL - custom-defined and generated + static PaletteArray ourCustomNTSCPalette; + static PaletteArray ourCustomPALPalette; + + private: + PaletteHandler() = delete; + PaletteHandler(const PaletteHandler&) = delete; + PaletteHandler(PaletteHandler&&) = delete; + PaletteHandler& operator=(const PaletteHandler&) = delete; + PaletteHandler& operator=(const PaletteHandler&&) = delete; +}; + +#endif // PALETTE_HANDLER_HXX diff --git a/src/common/module.mk b/src/common/module.mk index f7a228189..1aae6cd0a 100644 --- a/src/common/module.mk +++ b/src/common/module.mk @@ -11,6 +11,7 @@ MODULE_OBJS := \ src/common/Logger.o \ src/common/main.o \ src/common/MouseControl.o \ + src/common/PaletteHandler.o \ src/common/PhosphorHandler.o \ src/common/PhysicalJoystick.o \ src/common/PJoystickHandler.o \ diff --git a/src/common/tv_filters/AtariNTSC.cxx b/src/common/tv_filters/AtariNTSC.cxx index a0b9ef169..ad57a12f8 100644 --- a/src/common/tv_filters/AtariNTSC.cxx +++ b/src/common/tv_filters/AtariNTSC.cxx @@ -57,9 +57,15 @@ void AtariNTSC::generateKernels() const uInt8* ptr = myRGBPalette.data(); for(size_t entry = 0; entry < myRGBPalette.size() / 3; ++entry) { + #ifdef BLARGG_PALETTE float r = myImpl.to_float[*ptr++], g = myImpl.to_float[*ptr++], b = myImpl.to_float[*ptr++]; + #else + float r = (*ptr++) / 255.F * rgb_unit + rgb_offset, + g = (*ptr++) / 255.F * rgb_unit + rgb_offset, + b = (*ptr++) / 255.F * rgb_unit + rgb_offset; + #endif float y, i, q; RGB_TO_YIQ( r, g, b, y, i, q ); // Generate kernel @@ -319,8 +325,10 @@ void AtariNTSC::renderWithPhosphorThread(const uInt8* atari_in, const uInt32 in_ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void AtariNTSC::init(init_t& impl, const Setup& setup) { +#ifdef BLARGG_PALETTE impl.brightness = setup.brightness * (0.5F * rgb_unit) + rgb_offset; impl.contrast = setup.contrast * (0.5F * rgb_unit) + rgb_unit; +#endif impl.artifacts = setup.artifacts; if ( impl.artifacts > 0 ) @@ -334,6 +342,7 @@ void AtariNTSC::init(init_t& impl, const Setup& setup) initFilters(impl, setup); +#ifdef BLARGG_PALETTE /* generate gamma table */ if (true) /* was (gamma_size > 1) */ { @@ -341,19 +350,22 @@ void AtariNTSC::init(init_t& impl, const Setup& setup) float const gamma = 1.1333F - setup.gamma * 0.5F; /* match common PC's 2.2 gamma to TV's 2.65 gamma */ int i; - for ( i = 0; i < gamma_size; i++ ) - impl.to_float [i] = - powf( i * to_float, gamma ) * impl.contrast + impl.brightness; + for(i = 0; i < gamma_size; i++) + impl.to_float[i] = + powf(i * to_float, gamma) * impl.contrast + impl.brightness; } +#endif /* setup decoder matricies */ { + #ifdef BLARGG_PALETTE float hue = setup.hue * BSPF::PI_f + BSPF::PI_f / 180 * ext_decoder_hue; float sat = setup.saturation + 1; hue += BSPF::PI_f / 180 * (std_decoder_hue - ext_decoder_hue); - float s = sinf( hue ) * sat; - float c = cosf( hue ) * sat; + float s = sinf(hue)*sat; + float c = cosf(hue)*sat; + #endif float* out = impl.to_rgb.data(); int n; @@ -366,8 +378,13 @@ void AtariNTSC::init(init_t& impl, const Setup& setup) { float i = *in++; float q = *in++; + #ifdef BLARGG_PALETTE *out++ = i * c - q * s; *out++ = i * s + q * c; + #else + *out++ = i ; + *out++ = q; + #endif } while ( --n2 ); #if 0 // burst_count is always 0 @@ -544,16 +561,32 @@ void AtariNTSC::genKernel(init_t& impl, float y, float i, float q, uInt32* out) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const AtariNTSC::Setup AtariNTSC::TV_Composite = { +#ifdef BLARGG_PALETTE 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.15F, 0.0F, 0.0F, 0.0F +#else + 0.0F, 0.15F, 0.0F, 0.0F, 0.0F +#endif }; const AtariNTSC::Setup AtariNTSC::TV_SVideo = { +#ifdef BLARGG_PALETTE 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.45F, -1.0F, -1.0F, 0.0F +#else + 0.0F, 0.45F, -1.0F, -1.0F, 0.0F +#endif }; const AtariNTSC::Setup AtariNTSC::TV_RGB = { +#ifdef BLARGG_PALETTE 0.0F, 0.0F, 0.0F, 0.0F, 0.2F, 0.0F, 0.70F, -1.0F, -1.0F, -1.0F +#else + 0.2F, 0.70F, -1.0F, -1.0F, -1.0F +#endif }; const AtariNTSC::Setup AtariNTSC::TV_Bad = { +#ifdef BLARGG_PALETTE 0.1F, -0.3F, 0.3F, 0.25F, 0.2F, 0.0F, 0.1F, 0.5F, 0.5F, 0.5F +#else + 0.2F, 0.1F, 0.5F, 0.5F, 0.5F +#endif }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/tv_filters/AtariNTSC.hxx b/src/common/tv_filters/AtariNTSC.hxx index 4ae7b666f..eb75bce3d 100644 --- a/src/common/tv_filters/AtariNTSC.hxx +++ b/src/common/tv_filters/AtariNTSC.hxx @@ -46,6 +46,8 @@ #include "FrameBufferConstants.hxx" #include "bspf.hxx" +//#define BLARGG_PALETTE // also modify contrast, brightness, saturation, gamma and hue when defined + class AtariNTSC { public: @@ -57,14 +59,18 @@ class AtariNTSC struct Setup { // Basic parameters + #ifdef BLARGG_PALETTE float hue{0.F}; // -1 = -180 degrees +1 = +180 degrees float saturation{0.F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0) float contrast{0.F}; // -1 = dark (0.5) +1 = light (1.5) float brightness{0.F}; // -1 = dark (0.5) +1 = light (1.5) + #endif float sharpness{0.F}; // edge contrast enhancement/blurring // Advanced parameters + #ifdef BLARGG_PALETTE float gamma{0.F}; // -1 = dark (1.5) +1 = light (0.5) + #endif float resolution{0.F}; // image resolution float artifacts{0.F}; // artifacts caused by color changes float fringing{0.F}; // color artifacts caused by brightness changes @@ -127,7 +133,9 @@ class AtariNTSC burst_size = entry_size / burst_count, kernel_half = 16, kernel_size = kernel_half * 2 + 1, + #ifdef BLARGG_PALETTE gamma_size = 256, + #endif rgb_builder = ((1 << 21) | (1 << 11) | (1 << 1)), rgb_kernel_size = burst_size / alignment_count, @@ -162,16 +170,20 @@ class AtariNTSC struct init_t { std::array to_rgb{0.F}; + #ifdef BLARGG_PALETTE std::array to_float{0.F}; float contrast{0.F}; float brightness{0.F}; + #endif float artifacts{0.F}; float fringing{0.F}; std::array kernel{0.F}; init_t() { to_rgb.fill(0.0); + #ifdef BLARGG_PALETTE to_float.fill(0.0); + #endif kernel.fill(0.0); } }; diff --git a/src/common/tv_filters/NTSCFilter.cxx b/src/common/tv_filters/NTSCFilter.cxx index 6ec1afc8c..64f26da2b 100644 --- a/src/common/tv_filters/NTSCFilter.cxx +++ b/src/common/tv_filters/NTSCFilter.cxx @@ -74,13 +74,19 @@ string NTSCFilter::getPreset() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string NTSCFilter::setNextAdjustable() { - if(myPreset != Preset::CUSTOM) - return "'Custom' TV mode not selected"; + //if(myPreset != Preset::CUSTOM) + // return "'Custom' TV mode not selected"; +#ifdef BLARGG_PALETTE myCurrentAdjustable = (myCurrentAdjustable + 1) % 10; +#else + myCurrentAdjustable = (myCurrentAdjustable + 1) % 5; +#endif + ostringstream buf; buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type - << "' selected"; + << "' selected (" + << scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value) << "%)"; return buf.str(); } @@ -88,14 +94,19 @@ string NTSCFilter::setNextAdjustable() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string NTSCFilter::setPreviousAdjustable() { - if(myPreset != Preset::CUSTOM) - return "'Custom' TV mode not selected"; + //if(myPreset != Preset::CUSTOM) + // return "'Custom' TV mode not selected"; +#ifdef BLARGG_PALETTE if(myCurrentAdjustable == 0) myCurrentAdjustable = 9; +#else + if(myCurrentAdjustable == 0) myCurrentAdjustable = 4; +#endif else --myCurrentAdjustable; ostringstream buf; buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type - << "' selected"; + << "' selected (" + << scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value) << "%)"; return buf.str(); } @@ -103,8 +114,8 @@ string NTSCFilter::setPreviousAdjustable() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string NTSCFilter::increaseAdjustable() { - if(myPreset != Preset::CUSTOM) - return "'Custom' TV mode not selected"; + //if(myPreset != Preset::CUSTOM) + // return "'Custom' TV mode not selected"; uInt32 newval = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value); newval += 2; if(newval > 100) newval = 100; @@ -112,7 +123,7 @@ string NTSCFilter::increaseAdjustable() ostringstream buf; buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type - << "' set to " << newval; + << "' set to " << newval << "%"; setPreset(myPreset); return buf.str(); @@ -121,8 +132,8 @@ string NTSCFilter::increaseAdjustable() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string NTSCFilter::decreaseAdjustable() { - if(myPreset != Preset::CUSTOM) - return "'Custom' TV mode not selected"; + //if(myPreset != Preset::CUSTOM) + // return "'Custom' TV mode not selected"; uInt32 newval = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value); if(newval < 2) newval = 0; @@ -131,7 +142,7 @@ string NTSCFilter::decreaseAdjustable() ostringstream buf; buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type - << "' set to " << newval; + << "' set to " << newval << "%"; setPreset(myPreset); return buf.str(); @@ -140,13 +151,16 @@ string NTSCFilter::decreaseAdjustable() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void NTSCFilter::loadConfig(const Settings& settings) { + // Load adjustables for custom mode +#ifdef BLARGG_PALETTE myCustomSetup.hue = BSPF::clamp(settings.getFloat("tv.hue"), -1.0F, 1.0F); myCustomSetup.saturation = BSPF::clamp(settings.getFloat("tv.saturation"), -1.0F, 1.0F); myCustomSetup.contrast = BSPF::clamp(settings.getFloat("tv.contrast"), -1.0F, 1.0F); myCustomSetup.brightness = BSPF::clamp(settings.getFloat("tv.brightness"), -1.0F, 1.0F); - myCustomSetup.sharpness = BSPF::clamp(settings.getFloat("tv.sharpness"), -1.0F, 1.0F); myCustomSetup.gamma = BSPF::clamp(settings.getFloat("tv.gamma"), -1.0F, 1.0F); +#endif + myCustomSetup.sharpness = BSPF::clamp(settings.getFloat("tv.sharpness"), -1.0F, 1.0F); myCustomSetup.resolution = BSPF::clamp(settings.getFloat("tv.resolution"), -1.0F, 1.0F); myCustomSetup.artifacts = BSPF::clamp(settings.getFloat("tv.artifacts"), -1.0F, 1.0F); myCustomSetup.fringing = BSPF::clamp(settings.getFloat("tv.fringing"), -1.0F, 1.0F); @@ -157,12 +171,14 @@ void NTSCFilter::loadConfig(const Settings& settings) void NTSCFilter::saveConfig(Settings& settings) const { // Save adjustables for custom mode - settings.setValue("tv.hue", myCustomSetup.hue); - settings.setValue("tv.saturation", myCustomSetup.saturation); - settings.setValue("tv.contrast", myCustomSetup.contrast); - settings.setValue("tv.brightness", myCustomSetup.brightness); +#ifdef BLARGG_PALETTE + //settings.setValue("tv.hue", myCustomSetup.hue); + //settings.setValue("tv.saturation", myCustomSetup.saturation); + //settings.setValue("tv.contrast", myCustomSetup.contrast); + //settings.setValue("tv.brightness", myCustomSetup.brightness); + //settings.setValue("tv.gamma", myCustomSetup.gamma); +#endif settings.setValue("tv.sharpness", myCustomSetup.sharpness); - settings.setValue("tv.gamma", myCustomSetup.gamma); settings.setValue("tv.resolution", myCustomSetup.resolution); settings.setValue("tv.artifacts", myCustomSetup.artifacts); settings.setValue("tv.fringing", myCustomSetup.fringing); @@ -192,12 +208,14 @@ void NTSCFilter::getAdjustables(Adjustable& adjustable, Preset preset) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void NTSCFilter::setCustomAdjustables(Adjustable& adjustable) { - myCustomSetup.hue = scaleFrom100(adjustable.hue); - myCustomSetup.saturation = scaleFrom100(adjustable.saturation); - myCustomSetup.contrast = scaleFrom100(adjustable.contrast); - myCustomSetup.brightness = scaleFrom100(adjustable.brightness); +#ifdef BLARGG_PALETTE + //myCustomSetup.hue = scaleFrom100(adjustable.hue); + //myCustomSetup.saturation = scaleFrom100(adjustable.saturation); + //myCustomSetup.contrast = scaleFrom100(adjustable.contrast); + //myCustomSetup.brightness = scaleFrom100(adjustable.brightness); + //myCustomSetup.gamma = scaleFrom100(adjustable.gamma); +#endif myCustomSetup.sharpness = scaleFrom100(adjustable.sharpness); - myCustomSetup.gamma = scaleFrom100(adjustable.gamma); myCustomSetup.resolution = scaleFrom100(adjustable.resolution); myCustomSetup.artifacts = scaleFrom100(adjustable.artifacts); myCustomSetup.fringing = scaleFrom100(adjustable.fringing); @@ -208,12 +226,14 @@ void NTSCFilter::setCustomAdjustables(Adjustable& adjustable) void NTSCFilter::convertToAdjustable(Adjustable& adjustable, const AtariNTSC::Setup& setup) const { - adjustable.hue = scaleTo100(setup.hue); - adjustable.saturation = scaleTo100(setup.saturation); - adjustable.contrast = scaleTo100(setup.contrast); - adjustable.brightness = scaleTo100(setup.brightness); +#ifdef BLARGG_PALETTE + //adjustable.hue = scaleTo100(setup.hue); + //adjustable.saturation = scaleTo100(setup.saturation); + //adjustable.contrast = scaleTo100(setup.contrast); + //adjustable.brightness = scaleTo100(setup.brightness); + //adjustable.gamma = scaleTo100(setup.gamma); +#endif adjustable.sharpness = scaleTo100(setup.sharpness); - adjustable.gamma = scaleTo100(setup.gamma); adjustable.resolution = scaleTo100(setup.resolution); adjustable.artifacts = scaleTo100(setup.artifacts); adjustable.fringing = scaleTo100(setup.fringing); @@ -224,12 +244,16 @@ void NTSCFilter::convertToAdjustable(Adjustable& adjustable, AtariNTSC::Setup NTSCFilter::myCustomSetup = AtariNTSC::TV_Composite; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#ifdef BLARGG_PALETTE const std::array NTSCFilter::ourCustomAdjustables = { { { "contrast", &myCustomSetup.contrast }, { "brightness", &myCustomSetup.brightness }, { "hue", &myCustomSetup.hue }, { "saturation", &myCustomSetup.saturation }, { "gamma", &myCustomSetup.gamma }, +#else +const std::array NTSCFilter::ourCustomAdjustables = { { +#endif { "sharpness", &myCustomSetup.sharpness }, { "resolution", &myCustomSetup.resolution }, { "artifacts", &myCustomSetup.artifacts }, diff --git a/src/common/tv_filters/NTSCFilter.hxx b/src/common/tv_filters/NTSCFilter.hxx index b4a5e0e3d..f7e897916 100644 --- a/src/common/tv_filters/NTSCFilter.hxx +++ b/src/common/tv_filters/NTSCFilter.hxx @@ -51,8 +51,12 @@ class NTSCFilter /* Normally used in conjunction with custom mode, contains all aspects currently adjustable in NTSC TV emulation. */ struct Adjustable { + #ifdef BLARGG_PALETTE uInt32 hue, saturation, contrast, brightness, gamma, sharpness, resolution, artifacts, fringing, bleed; + #else + uInt32 sharpness, resolution, artifacts, fringing, bleed; + #endif }; public: @@ -139,7 +143,11 @@ class NTSCFilter float* value{nullptr}; }; uInt32 myCurrentAdjustable{0}; + #ifdef BLARGG_PALETTE static const std::array ourCustomAdjustables; + #else + static const std::array ourCustomAdjustables; + #endif private: // Following constructors and assignment operators not supported diff --git a/src/debugger/DiStella.cxx b/src/debugger/DiStella.cxx index 8aff0b568..c77d1eabf 100644 --- a/src/debugger/DiStella.cxx +++ b/src/debugger/DiStella.cxx @@ -1179,7 +1179,7 @@ void DiStella::outputColors() color = SECAM_COLOR[(byte >> 1) & 0x7]; myDisasmBuf << "$" << Base::HEX1 << (byte >> 4) << "|" << color; } - myDisasmBuf << std::setw(16 - color.length()) << std::setfill(' '); + myDisasmBuf << std::setw(int(16 - color.length())) << std::setfill(' '); // output address myDisasmBuf << "; $" << Base::HEX4 << myPC + myOffset << " " diff --git a/src/debugger/gui/CartARWidget.cxx b/src/debugger/gui/CartARWidget.cxx index 6037849f6..aa552d78e 100644 --- a/src/debugger/gui/CartARWidget.cxx +++ b/src/debugger/gui/CartARWidget.cxx @@ -16,6 +16,8 @@ //============================================================================ #include "CartAR.hxx" +#include "Debugger.hxx" +#include "CartDebug.hxx" #include "PopUpWidget.hxx" #include "CartARWidget.hxx" diff --git a/src/debugger/gui/CartDebugWidget.hxx b/src/debugger/gui/CartDebugWidget.hxx index 7bdcbf472..27c3befa5 100644 --- a/src/debugger/gui/CartDebugWidget.hxx +++ b/src/debugger/gui/CartDebugWidget.hxx @@ -19,7 +19,6 @@ #define CART_DEBUG_WIDGET_HXX class GuiObject; -class ButtonWidget; class StringListWidget; namespace GUI { @@ -29,8 +28,6 @@ namespace GUI { #include "Base.hxx" // not needed here, but all child classes need it #include "Command.hxx" #include "Widget.hxx" -#include "Debugger.hxx" -#include "CartDebug.hxx" class CartDebugWidget : public Widget, public CommandSender { diff --git a/src/debugger/gui/CartE0Widget.cxx b/src/debugger/gui/CartE0Widget.cxx index 12205c463..08ccc802a 100644 --- a/src/debugger/gui/CartE0Widget.cxx +++ b/src/debugger/gui/CartE0Widget.cxx @@ -49,7 +49,7 @@ string CartridgeE0Widget::romDescription() info << "Segment #" << seg << " accessible @ $" << Common::Base::HEX4 << (ADDR_BASE | segmentOffset) - << " - $" << (ADDR_BASE | segmentOffset + /*myCart.myBankSize - 1*/ 0x3FF) << ",\n"; + << " - $" << (ADDR_BASE | (segmentOffset + /*myCart.myBankSize - 1*/ 0x3FF)) << ",\n"; if (seg < 3) info << " Hotspots " << hotspotStr(0, seg, true) << " - " << hotspotStr(7, seg, true) << "\n"; else diff --git a/src/debugger/gui/CartEnhancedWidget.cxx b/src/debugger/gui/CartEnhancedWidget.cxx index f864a21c0..d955a803a 100644 --- a/src/debugger/gui/CartEnhancedWidget.cxx +++ b/src/debugger/gui/CartEnhancedWidget.cxx @@ -17,6 +17,8 @@ #include "PopUpWidget.hxx" +#include "Debugger.hxx" +#include "CartDebug.hxx" #include "CartEnhanced.hxx" #include "CartEnhancedWidget.hxx" diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index 5d8404d06..f62df7724 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -68,6 +68,11 @@ DebuggerDialog::DebuggerDialog(OSystem& osystem, DialogContainer& parent, Menu::AppMode::debugger); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +DebuggerDialog::~DebuggerDialog() +{ +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DebuggerDialog::loadConfig() { diff --git a/src/debugger/gui/DebuggerDialog.hxx b/src/debugger/gui/DebuggerDialog.hxx index b66ae37a6..f38e8b2dc 100644 --- a/src/debugger/gui/DebuggerDialog.hxx +++ b/src/debugger/gui/DebuggerDialog.hxx @@ -33,14 +33,16 @@ class TiaOutputWidget; class TiaZoomWidget; class CartDebugWidget; class CartRamWidget; +class OptionsDialog; +namespace GUI { + class MessageBox; +} namespace Common { struct Rect; } #include "Dialog.hxx" -#include "MessageBox.hxx" -#include "OptionsDialog.hxx" class DebuggerDialog : public Dialog { @@ -55,7 +57,7 @@ class DebuggerDialog : public Dialog DebuggerDialog(OSystem& osystem, DialogContainer& parent, int x, int y, int w, int h); - virtual ~DebuggerDialog() = default; + virtual ~DebuggerDialog(); const GUI::Font& lfont() const { return *myLFont; } const GUI::Font& nfont() const { return *myNFont; } diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 46078f09d..bf7d20abf 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -81,13 +81,6 @@ Console::Console(OSystem& osystem, unique_ptr& cart, myCart(std::move(cart)), myAudioSettings(audioSettings) { - // Load user-defined palette for this ROM - loadUserPalette(); - - // Generate custom palette - generateCustomPalette(0); - generateCustomPalette(1); - // Create subsystems for the console my6502 = make_unique(myOSystem.settings()); myRiot = make_unique(*this, myOSystem.settings()); @@ -441,7 +434,6 @@ void Console::setFormat(uInt32 format) myConsoleInfo.DisplayFormat = myDisplayFormat + autodetected; - setPalette(myOSystem.settings().getString("palette")); setTIAProperties(); initializeVideo(); // takes care of refreshing the screen initializeAudio(); // ensure that audio synthesis is set up to match emulation speed @@ -477,96 +469,6 @@ void Console::enableColorLoss(bool state) myTIA->enableColorLoss(state); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int Console::getPaletteNum(const string& name) const -{ - if(name == "z26") - return PaletteType::Z26; - - if(name == "user" && myUserPaletteDefined) - return PaletteType::User; - - if(name == "custom") - return PaletteType::Custom; - - return PaletteType::Standard; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::togglePalette() -{ - string palette, message; - palette = myOSystem.settings().getString("palette"); - - if(palette == "standard") // switch to z26 - { - palette = "z26"; - message = "Z26 palette"; - } - else if(palette == "z26") // switch to user or standard - { - // If we have a user-defined palette, it will come next in - // the sequence; otherwise loop back to the standard one - if(myUserPaletteDefined) - { - palette = "user"; - message = "User-defined palette"; - } - else - { - palette = "custom"; - message = "Custom palette"; - } - } - else if(palette == "user") // switch to custom - { - palette = "custom"; - message = "Custom palette"; - } - else // switch to standard mode if we get this far - { - palette = "standard"; - message = "Standard Stella palette"; - } - - myOSystem.settings().setValue("palette", palette); - myOSystem.frameBuffer().showMessage(message); - - setPalette(palette); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::setPalette(const string& type) -{ - // Look at all the palettes, since we don't know which one is - // currently active - static constexpr BSPF::array2D palettes = {{ - { &ourNTSCPalette, &ourPALPalette, &ourSECAMPalette }, - { &ourNTSCPaletteZ26, &ourPALPaletteZ26, &ourSECAMPaletteZ26 }, - { &ourUserNTSCPalette, &ourUserPALPalette, &ourUserSECAMPalette }, - { &ourCustomNTSCPalette, &ourCustomPALPalette, &ourSECAMPalette } - }}; - - // See which format we should be using - int paletteNum = getPaletteNum(type); - - if(paletteNum == PaletteType::Custom) - { - - } - - // Now consider the current display format - const PaletteArray* palette = - (myDisplayFormat.compare(0, 3, "PAL") == 0) ? palettes[paletteNum][1] : - (myDisplayFormat.compare(0, 5, "SECAM") == 0) ? palettes[paletteNum][2] : - palettes[paletteNum][0]; - - myOSystem.frameBuffer().setTIAPalette(*palette); - - if(myTIA->usingFixedColors()) - myTIA->enableFixedColors(true); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Console::toggleInter() { @@ -677,12 +579,7 @@ FBInitStatus Console::initializeVideo(bool full) myOSystem.frameBuffer().showFrameStats( myOSystem.settings().getBool(devSettings ? "dev.stats" : "plr.stats")); - generateCustomPalette(0); - generateCustomPalette(1); - generateColorLossPalette(); } - setPalette(myOSystem.settings().getString("palette")); - return fbstatus; } @@ -826,46 +723,6 @@ void Console::changeScanlineAdjust(int direction) myOSystem.frameBuffer().showMessage(ss.str()); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::changeColorPhaseShift(int direction) -{ - const char DEGREE = 0x1c; - const float NTSC_SHIFT = 26.2F; - const float PAL_SHIFT = 31.3F; // 360 / 11.5 - const bool isNTSC = myDisplayFormat == "NTSC" || myDisplayFormat == "NTSC50"; - const bool isPAL = myDisplayFormat == "PAL" || myDisplayFormat == "PAL60"; - - // SECAM is not supported - if(isNTSC || isPAL) - { - const string key = isNTSC ? "phase_ntsc" : "phase_pal"; - const float shift = isNTSC ? NTSC_SHIFT : PAL_SHIFT; - float phase = myOSystem.settings().getFloat(key); - - if(direction == +1) // increase color phase shift - { - phase += 0.3F; - phase = std::min(phase, shift + 4.5F); - } - else if(direction == -1) // decrease color phase shift - { - phase -= 0.3F; - phase = std::max(phase, shift - 4.5F); - } - myOSystem.settings().setValue(key, phase); - generateCustomPalette(isNTSC ? 0 : 1); - - myOSystem.settings().setValue("palette", "custom"); - setPalette("custom"); - - ostringstream ss; - ss << "Color phase shift at " - << std::fixed << std::setprecision(1) << phase << DEGREE; - - myOSystem.frameBuffer().showMessage(ss.str()); - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Console::setTIAProperties() { @@ -1073,202 +930,6 @@ unique_ptr Console::getControllerPort(const Controller::Type type, return controller; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::loadUserPalette() -{ - if (!myOSystem.checkUserPalette(true)) - return; - - const string& palette = myOSystem.paletteFile(); - ifstream in(palette, std::ios::binary); - - // Now that we have valid data, create the user-defined palettes - std::array pixbuf; // Temporary buffer for one 24-bit pixel - - for(int i = 0; i < 128; i++) // NTSC palette - { - in.read(reinterpret_cast(pixbuf.data()), 3); - 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(pixbuf.data()), 3); - uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); - ourUserPALPalette[(i<<1)] = pixel; - } - - std::array secam; // All 8 24-bit pixels, plus 8 colorloss pixels - for(int i = 0; i < 8; i++) // SECAM palette - { - in.read(reinterpret_cast(pixbuf.data()), 3); - uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); - secam[(i<<1)] = pixel; - secam[(i<<1)+1] = 0; - } - uInt32* ptr = ourUserSECAMPalette.data(); - for(int i = 0; i < 16; ++i) - { - const uInt32* s = secam.data(); - for(int j = 0; j < 16; ++j) - *ptr++ = *s++; - } - - myUserPaletteDefined = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::generateCustomPalette(int type) -{ - constexpr int NUM_CHROMA = 16; - constexpr int NUM_LUMA = 8; - constexpr float SATURATION = 0.25F; - - float color[NUM_CHROMA][2] = {{0.0F}}; - - if(type == 0) - { - // YIQ is YUV shifted by 33° - constexpr float offset = 33 * (2 * BSPF::PI_f / 360); - const float shift = myOSystem.settings().getFloat("phase_ntsc") * - (2 * BSPF::PI_f / 360); - - // color 0 is grayscale - for(int chroma = 1; chroma < NUM_CHROMA; chroma++) - { - color[chroma][0] = SATURATION * sin(offset + shift * (chroma - 1)); - color[chroma][1] = SATURATION * sin(offset + shift * (chroma - 1 - BSPF::PI_f)); - } - - 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++) - { - const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90 - - float R = Y + 0.956F * I + 0.621F * Q; - float G = Y - 0.272F * I - 0.647F * Q; - float B = Y - 1.106F * I + 1.703F * Q; - - if(R < 0) R = 0; - if(G < 0) G = 0; - if(B < 0) B = 0; - - R = powf(R, 0.9F); - G = powf(G, 0.9F); - B = powf(B, 0.9F); - - if(R > 1) R = 1; - if(G > 1) G = 1; - if(B > 1) B = 1; - - int r = R * 255.F; - int g = G * 255.F; - int b = B * 255.F; - - ourCustomNTSCPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b; - } - } - } - else - { - constexpr float offset = 180 * (2 * BSPF::PI_f / 360); - float shift = myOSystem.settings().getFloat("phase_pal") * - (2 * BSPF::PI_f / 360); - constexpr float fixedShift = 22.5F * (2 * BSPF::PI_f / 360); - - // colors 0, 1, 14 and 15 are grayscale - for(int chroma = 2; chroma < NUM_CHROMA - 2; chroma++) - { - int idx = NUM_CHROMA - 1 - chroma; - color[idx][0] = SATURATION * sinf(offset - fixedShift * chroma); - if ((idx & 1) == 0) - color[idx][1] = SATURATION * sinf(offset - shift * (chroma - 3.5F) / 2.F); - else - color[idx][1] = SATURATION * -sinf(offset - shift * chroma / 2.F); - } - - 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++) - { - const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90 - - // 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; - //float G = 1.704 * Y - 0.590 * R - 0.194 * B; - - if(R < 0) R = 0.0; - if(G < 0) G = 0.0; - if(B < 0) B = 0.0; - - R = powf(R, 1.2); - G = powf(G, 1.2); - B = powf(B, 1.2); - - if(R > 1) R = 1; - if(G > 1) G = 1; - if(B > 1) B = 1; - - int r = R * 255.F; - int g = G * 255.F; - int b = B * 255.F; - - ourCustomPALPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b; - } - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::generateColorLossPalette() -{ - // Look at all the palettes, since we don't know which one is - // currently active - std::array palette = { - ourNTSCPalette.data(), ourPALPalette.data(), ourSECAMPalette.data(), - ourNTSCPaletteZ26.data(), ourPALPaletteZ26.data(), ourSECAMPaletteZ26.data(), - nullptr, nullptr, nullptr, - ourCustomNTSCPalette.data(), ourCustomPALPalette.data(), ourSECAMPalette.data(), - }; - if(myUserPaletteDefined) - { - palette[6] = ourUserNTSCPalette.data(); - palette[7] = ourUserPALPalette.data(); - palette[8] = ourUserSECAMPalette.data(); - } - - for(int i = 0; i < 3 * PaletteType::NumTypes; ++i) - { - if(palette[i] == nullptr) - continue; - - // Fill the odd numbered palette entries with gray values (calculated - // using the standard RGB -> grayscale conversion formula) - for(int j = 0; j < 128; ++j) - { - const uInt32 pixel = palette[i][(j<<1)]; - const uInt8 r = (pixel >> 16) & 0xff; - const uInt8 g = (pixel >> 8) & 0xff; - const uInt8 b = (pixel >> 0) & 0xff; - const uInt8 sum = static_cast((r * 0.2989) + (g * 0.5870) + (b * 0.1140)); - palette[i][(j<<1)+1] = (sum << 16) + (sum << 8) + sum; - } - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float Console::getFramerate() const { @@ -1340,234 +1001,3 @@ void Console::stateChanged(EventHandlerState state) { // only the CompuMate used to care about state changes } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::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, - 0xbbbb35, 0, 0xd2d240, 0, 0xe8e84a, 0, 0xfcfc54, 0, - 0x7c2c00, 0, 0x904811, 0, 0xa26221, 0, 0xb47a30, 0, - 0xc3903d, 0, 0xd2a44a, 0, 0xdfb755, 0, 0xecc860, 0, - 0x901c00, 0, 0xa33915, 0, 0xb55328, 0, 0xc66c3a, 0, - 0xd5824a, 0, 0xe39759, 0, 0xf0aa67, 0, 0xfcbc74, 0, - 0x940000, 0, 0xa71a1a, 0, 0xb83232, 0, 0xc84848, 0, - 0xd65c5c, 0, 0xe46f6f, 0, 0xf08080, 0, 0xfc9090, 0, - 0x840064, 0, 0x97197a, 0, 0xa8308f, 0, 0xb846a2, 0, - 0xc659b3, 0, 0xd46cc3, 0, 0xe07cd2, 0, 0xec8ce0, 0, - 0x500084, 0, 0x68199a, 0, 0x7d30ad, 0, 0x9246c0, 0, - 0xa459d0, 0, 0xb56ce0, 0, 0xc57cee, 0, 0xd48cfc, 0, - 0x140090, 0, 0x331aa3, 0, 0x4e32b5, 0, 0x6848c6, 0, - 0x7f5cd5, 0, 0x956fe3, 0, 0xa980f0, 0, 0xbc90fc, 0, - 0x000094, 0, 0x181aa7, 0, 0x2d32b8, 0, 0x4248c8, 0, - 0x545cd6, 0, 0x656fe4, 0, 0x7580f0, 0, 0x8490fc, 0, - 0x001c88, 0, 0x183b9d, 0, 0x2d57b0, 0, 0x4272c2, 0, - 0x548ad2, 0, 0x65a0e1, 0, 0x75b5ef, 0, 0x84c8fc, 0, - 0x003064, 0, 0x185080, 0, 0x2d6d98, 0, 0x4288b0, 0, - 0x54a0c5, 0, 0x65b7d9, 0, 0x75cceb, 0, 0x84e0fc, 0, - 0x004030, 0, 0x18624e, 0, 0x2d8169, 0, 0x429e82, 0, - 0x54b899, 0, 0x65d1ae, 0, 0x75e7c2, 0, 0x84fcd4, 0, - 0x004400, 0, 0x1a661a, 0, 0x328432, 0, 0x48a048, 0, - 0x5cba5c, 0, 0x6fd26f, 0, 0x80e880, 0, 0x90fc90, 0, - 0x143c00, 0, 0x355f18, 0, 0x527e2d, 0, 0x6e9c42, 0, - 0x87b754, 0, 0x9ed065, 0, 0xb4e775, 0, 0xc8fc84, 0, - 0x303800, 0, 0x505916, 0, 0x6d762b, 0, 0x88923e, 0, - 0xa0ab4f, 0, 0xb7c25f, 0, 0xccd86e, 0, 0xe0ec7c, 0, - 0x482c00, 0, 0x694d14, 0, 0x866a26, 0, 0xa28638, 0, - 0xbb9f47, 0, 0xd2b656, 0, 0xe8cc63, 0, 0xfce070, 0 -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::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 - 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, - 0x1d0f00, 0, 0x3f2700, 0, 0x614900, 0, 0x836b01, 0, // 1b0 2 - 0xa58d23, 0, 0xc7af45, 0, 0xe9d167, 0, 0xffe789, 0, // was ..0xfff389 - 0x002400, 0, 0x004600, 0, 0x216800, 0, 0x438a07, 0, // 1c8 3 - 0x65ac29, 0, 0x87ce4b, 0, 0xa9f06d, 0, 0xcbff8f, 0, - 0x340000, 0, 0x561400, 0, 0x783602, 0, 0x9a5824, 0, // 1e0 4 - 0xbc7a46, 0, 0xde9c68, 0, 0xffbe8a, 0, 0xffd0ad, 0, // was ..0xffe0ac - 0x002700, 0, 0x004900, 0, 0x0c6b0c, 0, 0x2e8d2e, 0, // 1f8 5 - 0x50af50, 0, 0x72d172, 0, 0x94f394, 0, 0xb6ffb6, 0, - 0x3d0008, 0, 0x610511, 0, 0x832733, 0, 0xa54955, 0, // 210 6 - 0xc76b77, 0, 0xe98d99, 0, 0xffafbb, 0, 0xffd1d7, 0, // was 0x3f0000..0xffd1dd - 0x001e12, 0, 0x004228, 0, 0x046540, 0, 0x268762, 0, // 228 7 - 0x48a984, 0, 0x6acba6, 0, 0x8cedc8, 0, 0xafffe0, 0, // was 0x002100, 0x00431e..0xaeffff - 0x300025, 0, 0x5f0047, 0, 0x811e69, 0, 0xa3408b, 0, // 240 8 - 0xc562ad, 0, 0xe784cf, 0, 0xffa8ea, 0, 0xffc9f2, 0, // was ..0xffa6f1, 0xffc8ff - 0x001431, 0, 0x003653, 0, 0x0a5875, 0, 0x2c7a97, 0, // 258 9 - 0x4e9cb9, 0, 0x70bedb, 0, 0x92e0fd, 0, 0xb4ffff, 0, - 0x2c0052, 0, 0x4e0074, 0, 0x701d96, 0, 0x923fb8, 0, // 270 a - 0xb461da, 0, 0xd683fc, 0, 0xe2a5ff, 0, 0xeec9ff, 0, // was ..0xf8a5ff, 0xffc7ff - 0x001759, 0, 0x00247c, 0, 0x1d469e, 0, 0x3f68c0, 0, // 288 b - 0x618ae2, 0, 0x83acff, 0, 0xa5ceff, 0, 0xc7f0ff, 0, - 0x12006d, 0, 0x34038f, 0, 0x5625b1, 0, 0x7847d3, 0, // 2a0 c - 0x9a69f5, 0, 0xb48cff, 0, 0xc9adff, 0, 0xe1d1ff, 0, // was ..0xbc8bff, 0xdeadff, 0xffcfff, - 0x000070, 0, 0x161292, 0, 0x3834b4, 0, 0x5a56d6, 0, // 2b8 d - 0x7c78f8, 0, 0x9e9aff, 0, 0xc0bcff, 0, 0xe2deff, 0, - 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2d0 e - 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, - 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2e8 f - 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::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, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0 -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::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, - 0x94a414, 0, 0xa8b828, 0, 0xbccc3c, 0, 0xd0e050, 0, - 0x673900, 0, 0x7b4d00, 0, 0x8f6100, 0, 0xa37513, 0, - 0xb78927, 0, 0xcb9d3b, 0, 0xdfb14f, 0, 0xf3c563, 0, - 0x7b2504, 0, 0x8f3918, 0, 0xa34d2c, 0, 0xb76140, 0, - 0xcb7554, 0, 0xdf8968, 0, 0xf39d7c, 0, 0xffb190, 0, - 0x7d122c, 0, 0x912640, 0, 0xa53a54, 0, 0xb94e68, 0, - 0xcd627c, 0, 0xe17690, 0, 0xf58aa4, 0, 0xff9eb8, 0, - 0x730871, 0, 0x871c85, 0, 0x9b3099, 0, 0xaf44ad, 0, - 0xc358c1, 0, 0xd76cd5, 0, 0xeb80e9, 0, 0xff94fd, 0, - 0x5d0b92, 0, 0x711fa6, 0, 0x8533ba, 0, 0x9947ce, 0, - 0xad5be2, 0, 0xc16ff6, 0, 0xd583ff, 0, 0xe997ff, 0, - 0x401599, 0, 0x5429ad, 0, 0x683dc1, 0, 0x7c51d5, 0, - 0x9065e9, 0, 0xa479fd, 0, 0xb88dff, 0, 0xcca1ff, 0, - 0x252593, 0, 0x3939a7, 0, 0x4d4dbb, 0, 0x6161cf, 0, - 0x7575e3, 0, 0x8989f7, 0, 0x9d9dff, 0, 0xb1b1ff, 0, - 0x0f3480, 0, 0x234894, 0, 0x375ca8, 0, 0x4b70bc, 0, - 0x5f84d0, 0, 0x7398e4, 0, 0x87acf8, 0, 0x9bc0ff, 0, - 0x04425a, 0, 0x18566e, 0, 0x2c6a82, 0, 0x407e96, 0, - 0x5492aa, 0, 0x68a6be, 0, 0x7cbad2, 0, 0x90cee6, 0, - 0x044f30, 0, 0x186344, 0, 0x2c7758, 0, 0x408b6c, 0, - 0x549f80, 0, 0x68b394, 0, 0x7cc7a8, 0, 0x90dbbc, 0, - 0x0f550a, 0, 0x23691e, 0, 0x377d32, 0, 0x4b9146, 0, - 0x5fa55a, 0, 0x73b96e, 0, 0x87cd82, 0, 0x9be196, 0, - 0x1f5100, 0, 0x336505, 0, 0x477919, 0, 0x5b8d2d, 0, - 0x6fa141, 0, 0x83b555, 0, 0x97c969, 0, 0xabdd7d, 0, - 0x344600, 0, 0x485a00, 0, 0x5c6e14, 0, 0x708228, 0, - 0x84963c, 0, 0x98aa50, 0, 0xacbe64, 0, 0xc0d278, 0, - 0x463e00, 0, 0x5a5205, 0, 0x6e6619, 0, 0x827a2d, 0, - 0x968e41, 0, 0xaaa255, 0, 0xbeb669, 0, 0xd2ca7d, 0 -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::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, - 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0, - 0x533a00, 0, 0x674e00, 0, 0x7b6203, 0, 0x8f7617, 0, - 0xa38a2b, 0, 0xb79e3f, 0, 0xcbb253, 0, 0xdfc667, 0, - 0x1b5800, 0, 0x2f6c00, 0, 0x438001, 0, 0x579415, 0, - 0x6ba829, 0, 0x7fbc3d, 0, 0x93d051, 0, 0xa7e465, 0, - 0x6a2900, 0, 0x7e3d12, 0, 0x925126, 0, 0xa6653a, 0, - 0xba794e, 0, 0xce8d62, 0, 0xe2a176, 0, 0xf6b58a, 0, - 0x075b00, 0, 0x1b6f11, 0, 0x2f8325, 0, 0x439739, 0, - 0x57ab4d, 0, 0x6bbf61, 0, 0x7fd375, 0, 0x93e789, 0, - 0x741b2f, 0, 0x882f43, 0, 0x9c4357, 0, 0xb0576b, 0, - 0xc46b7f, 0, 0xd87f93, 0, 0xec93a7, 0, 0xffa7bb, 0, - 0x00572e, 0, 0x106b42, 0, 0x247f56, 0, 0x38936a, 0, - 0x4ca77e, 0, 0x60bb92, 0, 0x74cfa6, 0, 0x88e3ba, 0, - 0x6d165f, 0, 0x812a73, 0, 0x953e87, 0, 0xa9529b, 0, - 0xbd66af, 0, 0xd17ac3, 0, 0xe58ed7, 0, 0xf9a2eb, 0, - 0x014c5e, 0, 0x156072, 0, 0x297486, 0, 0x3d889a, 0, - 0x519cae, 0, 0x65b0c2, 0, 0x79c4d6, 0, 0x8dd8ea, 0, - 0x5f1588, 0, 0x73299c, 0, 0x873db0, 0, 0x9b51c4, 0, - 0xaf65d8, 0, 0xc379ec, 0, 0xd78dff, 0, 0xeba1ff, 0, - 0x123b87, 0, 0x264f9b, 0, 0x3a63af, 0, 0x4e77c3, 0, - 0x628bd7, 0, 0x769feb, 0, 0x8ab3ff, 0, 0x9ec7ff, 0, - 0x451e9d, 0, 0x5932b1, 0, 0x6d46c5, 0, 0x815ad9, 0, - 0x956eed, 0, 0xa982ff, 0, 0xbd96ff, 0, 0xd1aaff, 0, - 0x2a2b9e, 0, 0x3e3fb2, 0, 0x5253c6, 0, 0x6667da, 0, - 0x7a7bee, 0, 0x8e8fff, 0, 0xa2a3ff, 0, 0xb6b7ff, 0, - 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, - 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0, - 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, - 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0 -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::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, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0 -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourUserNTSCPalette = { 0 }; // filled from external file - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourUserPALPalette = { 0 }; // filled from external file - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourUserSECAMPalette = { 0 }; // filled from external file - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourCustomNTSCPalette = { 0 }; // filled by function - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourCustomPALPalette = { 0 }; // filled by function diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx index 9ff4b002c..ac26415d7 100644 --- a/src/emucore/Console.hxx +++ b/src/emucore/Console.hxx @@ -39,7 +39,6 @@ class AudioSettings; #include "FrameBufferConstants.hxx" #include "Serializable.hxx" #include "EventHandlerConstants.hxx" -#include "NTSCFilter.hxx" #include "EmulationTiming.hxx" #include "ConsoleTiming.hxx" #include "frame-manager/AbstractFrameManager.hxx" @@ -204,23 +203,6 @@ class Console : public Serializable, public ConsoleIO */ string getFormatString() const { return myDisplayFormat; } - /** - Toggle between the available palettes. - */ - void togglePalette(); - - /** - Generates a custom palette, based on user defined phase shifts. - */ - void generateCustomPalette(int type); - - /** - Sets the palette according to the given palette name. - - @param palette The palette to switch to. - */ - void setPalette(const string& palette); - /** Toggle interpolation on/off */ @@ -288,16 +270,6 @@ class Console : public Serializable, public ConsoleIO */ void changeScanlineAdjust(int direction); - /** - Change the "phase shift" variable. - Note that there are two of these (NTSC and PAL). The currently - active mode will determine which one is used. - - @param direction +1 indicates increase, -1 indicates decrease. - - */ - void changeColorPhaseShift(int direction); - /** Returns the current framerate. */ @@ -379,35 +351,10 @@ class Console : public Serializable, public ConsoleIO unique_ptr getControllerPort(const Controller::Type type, const Controller::Jack port, const string& romMd5); - /** - Loads a user-defined palette file (from OSystem::paletteFile), filling the - appropriate user-defined palette arrays. - */ - void loadUserPalette(); - - /** - Loads all defined palettes with PAL color-loss data, even those that - normally can't have it enabled (NTSC), since it's also used for - 'greying out' the frame in the debugger. - */ - void generateColorLossPalette(); - - int getPaletteNum(const string& name) const; - - void toggleTIABit(TIABit bit, const string& bitname, bool show = true) const; void toggleTIACollision(TIABit bit, const string& bitname, bool show = true) const; private: - - enum PaletteType { - Standard, - Z26, - User, - Custom, - NumTypes - }; - // Reference to the osystem object OSystem& myOSystem; @@ -457,10 +404,6 @@ class Console : public Serializable, public ConsoleIO // Is the TV format autodetected? bool myFormatAutodetected{false}; - // Indicates whether an external palette was found and - // successfully loaded - bool myUserPaletteDefined{false}; - // Contains detailed info about this console ConsoleInfo myConsoleInfo; @@ -474,25 +417,6 @@ class Console : public Serializable, public ConsoleIO // The audio settings AudioSettings& myAudioSettings; - // Table of RGB values for NTSC, PAL and SECAM - static PaletteArray ourNTSCPalette; - static PaletteArray ourPALPalette; - static PaletteArray ourSECAMPalette; - - // Table of RGB values for NTSC, PAL and SECAM - Z26 version - static PaletteArray ourNTSCPaletteZ26; - static PaletteArray ourPALPaletteZ26; - static PaletteArray ourSECAMPaletteZ26; - - // Table of RGB values for NTSC, PAL and SECAM - user-defined - static PaletteArray ourUserNTSCPalette; - static PaletteArray ourUserPALPalette; - static PaletteArray ourUserSECAMPalette; - - // Table of RGB values for NTSC, PAL - custom-defined - static PaletteArray ourCustomNTSCPalette; - static PaletteArray ourCustomPALPalette; - private: // Following constructors and assignment operators not supported Console() = delete; diff --git a/src/emucore/ConsoleTiming.hxx b/src/emucore/ConsoleTiming.hxx index 1f75db469..fd43caa98 100644 --- a/src/emucore/ConsoleTiming.hxx +++ b/src/emucore/ConsoleTiming.hxx @@ -25,7 +25,8 @@ enum class ConsoleTiming { ntsc, // console with CPU running at 1.193182 MHz, NTSC colours pal, // console with CPU running at 1.182298 MHz, PAL colours - secam // console with CPU running at 1.187500 MHz, SECAM colours + secam, // console with CPU running at 1.187500 MHz, SECAM colours + numTimings }; #endif // CONSOLE_TIMING_HXX diff --git a/src/emucore/Event.hxx b/src/emucore/Event.hxx index 915461e97..fba15b6fb 100644 --- a/src/emucore/Event.hxx +++ b/src/emucore/Event.hxx @@ -22,7 +22,6 @@ #include #include "bspf.hxx" -#include "StellaKeys.hxx" /** @author Stephen Anthony, Christian Speckner, Thomas Jentzsch @@ -92,6 +91,7 @@ class Event TogglePauseMode, StartPauseMode, OptionsMenuMode, CmdMenuMode, DebuggerMode, ExitMode, TakeSnapshot, ToggleContSnapshots, ToggleContSnapshotsFrame, + ToggleTurbo, NextState, PreviousState, LoadState, SaveState, SaveAllStates, LoadAllStates, @@ -100,12 +100,15 @@ class Event Unwind1Menu, Unwind10Menu, UnwindAllMenu, RewindPause, UnwindPause, - FormatDecrease, FormatIncrease, TogglePalette, ToggleColorLoss, + FormatDecrease, FormatIncrease, PaletteDecrease, PaletteIncrease, ToggleColorLoss, + PreviousPaletteAttribute, NextPaletteAttribute, + PaletteAttributeDecrease, PaletteAttributeIncrease, ToggleFullScreen, VidmodeDecrease, VidmodeIncrease, VCenterDecrease, VCenterIncrease, ScanlineAdjustDecrease, ScanlineAdjustIncrease, OverscanDecrease, OverscanIncrease, VidmodeStd, VidmodeRGB, VidmodeSVideo, VidModeComposite, VidModeBad, VidModeCustom, + PreviousVideoMode, NextVideoMode, PreviousAttribute, NextAttribute, DecreaseAttribute, IncreaseAttribute, ScanlinesDecrease, ScanlinesIncrease, PhosphorDecrease, PhosphorIncrease, TogglePhosphor, ToggleInter, ToggleJitter, @@ -118,10 +121,7 @@ class Event ToggleCollisions, ToggleBits, ToggleFixedColors, ToggleFrameStats, ToggleSAPortOrder, ExitGame, - // add new events from here to avoid that user remapped events get overwritten - ToggleTurbo, - ColorShiftDecrease, ColorShiftIncrease, LastType }; @@ -136,7 +136,7 @@ class Event }; // Event list version, update only if the id of existing(!) event types changed - static constexpr Int32 VERSION = 3; + static constexpr Int32 VERSION = 4; using EventSet = std::set; diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index c9fa85835..362625909 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -22,6 +22,7 @@ #include "Base.hxx" #include "Console.hxx" +#include "PaletteHandler.hxx" #include "FrameBuffer.hxx" #include "FSNode.hxx" #include "OSystem.hxx" @@ -435,12 +436,20 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) if (pressed) myOSystem.console().changeScanlineAdjust(+1); return; - case Event::ColorShiftDecrease: - if (pressed) myOSystem.console().changeColorPhaseShift(-1); + case Event::PreviousPaletteAttribute: + if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(false); return; - case Event::ColorShiftIncrease: - if (pressed) myOSystem.console().changeColorPhaseShift(+1); + case Event::NextPaletteAttribute: + if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(true); + return; + + case Event::PaletteAttributeDecrease: + if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().changeAdjustable(false); + return; + + case Event::PaletteAttributeIncrease: + if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().changeAdjustable(true); return; case Event::ToggleFullScreen: @@ -455,6 +464,14 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) if (pressed) myOSystem.frameBuffer().changeOverscan(1); return; + case Event::PreviousVideoMode: + if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().changeNTSC(false); + return; + + case Event::NextVideoMode: + if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().changeNTSC(true); + return; + case Event::VidmodeStd: if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::OFF); return; @@ -539,8 +556,12 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) if (pressed && !repeated) myOSystem.console().toggleColorLoss(); return; - case Event::TogglePalette: - if (pressed && !repeated) myOSystem.console().togglePalette(); + case Event::PaletteDecrease: + if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(false); + return; + + case Event::PaletteIncrease: + if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(true); return; case Event::ToggleInter: @@ -1929,21 +1950,28 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { { { Event::VCenterIncrease, "Move display down", "" }, { Event::FormatDecrease, "Decrease display format", "" }, { Event::FormatIncrease, "Increase display format", "" }, - { Event::TogglePalette, "Switch palette (Std./Z26/User/Cust.)", "" }, - { Event::ColorShiftDecrease, "Decrease custom palette phase shift", "" }, - { Event::ColorShiftIncrease, "Increase custom palette phase shift", "" }, + // Palette settings + { Event::PaletteDecrease, "Switch to previous palette", "" }, + { Event::PaletteIncrease, "Switch to next palette", "" }, + { Event::PreviousPaletteAttribute,"Select previous palette attribute", "" }, + { Event::NextPaletteAttribute, "Select next palette attribute", "" }, + { Event::PaletteAttributeDecrease,"Decrease selected palette attribute", "" }, + { Event::PaletteAttributeIncrease,"Increase selected palette attribute", "" }, { Event::ToggleInter, "Toggle display interpolation", "" }, - // TV effects: + // Blargg TV effects: { Event::VidmodeStd, "Disable TV effects", "" }, { Event::VidmodeRGB, "Select 'RGB' preset", "" }, { Event::VidmodeSVideo, "Select 'S-Video' preset", "" }, { Event::VidModeComposite, "Select 'Composite' preset", "" }, { Event::VidModeBad, "Select 'Badly adjusted' preset", "" }, { Event::VidModeCustom, "Select 'Custom' preset", "" }, + { Event::PreviousVideoMode, "Select previous TV effect mode preset", "" }, + { Event::NextVideoMode, "Select next TV effect mode preset", "" }, { Event::PreviousAttribute, "Select previous 'Custom' attribute", "" }, { Event::NextAttribute, "Select next 'Custom' attribute", "" }, { Event::DecreaseAttribute, "Decrease selected 'Custom' attribute", "" }, { Event::IncreaseAttribute, "Increase selected 'Custom' attribute", "" }, + // Other TV effects { Event::TogglePhosphor, "Toggle 'phosphor' effect", "" }, { Event::PhosphorDecrease, "Decrease 'phosphor' blend", "" }, { Event::PhosphorIncrease, "Increase 'phosphor' blend", "" }, @@ -2058,7 +2086,10 @@ const Event::EventSet EventHandler::AudioVideoEvents = { Event::VCenterDecrease, Event::VCenterIncrease, Event::ScanlineAdjustDecrease, Event::ScanlineAdjustIncrease, Event::OverscanDecrease, Event::OverscanIncrease, - Event::TogglePalette, Event::ColorShiftDecrease, Event::ColorShiftIncrease, + Event::PaletteDecrease, Event::PaletteIncrease, + Event::PreviousVideoMode, Event::NextVideoMode, + Event::PreviousPaletteAttribute, Event::NextPaletteAttribute, + Event::PaletteAttributeDecrease, Event::PaletteAttributeIncrease, Event::ToggleInter }; diff --git a/src/emucore/EventHandler.hxx b/src/emucore/EventHandler.hxx index 8fe4c7821..6d19b685b 100644 --- a/src/emucore/EventHandler.hxx +++ b/src/emucore/EventHandler.hxx @@ -25,6 +25,7 @@ class OSystem; class MouseControl; class DialogContainer; class PhysicalJoystick; +class Variant; namespace GUI { class Font; @@ -36,7 +37,6 @@ namespace GUI { #include "StellaKeys.hxx" #include "PKeyboardHandler.hxx" #include "PJoystickHandler.hxx" -#include "Variant.hxx" #include "bspf.hxx" /** @@ -468,7 +468,7 @@ class EventHandler #else PNG_SIZE = 0, #endif - EMUL_ACTIONLIST_SIZE = 149 + PNG_SIZE + COMBO_SIZE, + EMUL_ACTIONLIST_SIZE = 152 + PNG_SIZE + COMBO_SIZE, MENU_ACTIONLIST_SIZE = 18 ; diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index ce2d4cf46..14f620373 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -171,10 +171,9 @@ void FrameBuffer::setupFonts() // However, we have to make sure all Dialogs are sized using the fontsize. int zoom_h = (fd.height * 4 * 2) / GUI::stellaMediumDesc.height; int zoom_w = (fd.maxwidth * 4 * 2) / GUI::stellaMediumDesc.maxwidth; - myTIAMinZoom = std::max(zoom_w, zoom_h) / 4.F; // round to 25% steps + myTIAMinZoom = std::max(std::max(zoom_w, zoom_h) / 4.F, 2.F); // round to 25% steps, >= 200% } - // The font used by the ROM launcher const string& lf = myOSystem.settings().getString("launcherfont"); @@ -310,7 +309,7 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type, } if(!myMsg.surface) - myMsg.surface = allocateSurface(FBMinimum::Width, font().getFontHeight() * 1.5); + myMsg.surface = allocateSurface(font().getMaxCharWidth() * 56, font().getFontHeight() * 1.5); #endif // Print initial usage message, but only print it later if the status has changed diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index ccf6838cb..8d60f6fb1 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -49,6 +49,7 @@ #include "CartDetector.hxx" #include "FrameBuffer.hxx" #include "TIASurface.hxx" +#include "PaletteHandler.hxx" #include "TIAConstants.hxx" #include "Settings.hxx" #include "PropsSet.hxx" @@ -243,6 +244,8 @@ void OSystem::saveConfig() Logger::debug("Saving TV effects options ..."); myFrameBuffer->tiaSurface().ntsc().saveConfig(settings()); + Logger::debug("Saving palette settings..."); + myFrameBuffer->tiaSurface().paletteHandler().saveConfig(settings()); } Logger::debug("Saving config options ..."); diff --git a/src/emucore/OSystem.hxx b/src/emucore/OSystem.hxx index b23cbdb83..2bc5368c6 100644 --- a/src/emucore/OSystem.hxx +++ b/src/emucore/OSystem.hxx @@ -41,7 +41,7 @@ class AudioSettings; class Menu; class MessageMenu; class TimeMachine; - class VideoDialog; + class VideoAudioDialog; #endif #ifdef PNG_SUPPORT class PNGLibrary; diff --git a/src/emucore/PointingDevice.cxx b/src/emucore/PointingDevice.cxx index 1a2c781b4..4d91d010c 100644 --- a/src/emucore/PointingDevice.cxx +++ b/src/emucore/PointingDevice.cxx @@ -15,6 +15,8 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include + #include "Control.hxx" #include "Event.hxx" #include "System.hxx" diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index c1c64dd20..07c41e0f3 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -21,6 +21,7 @@ #include "Version.hxx" #include "Logger.hxx" #include "AudioSettings.hxx" +#include "PaletteHandler.hxx" #include "Paddles.hxx" #ifdef DEBUGGER_SUPPORT @@ -45,9 +46,7 @@ Settings::Settings() setPermanent("center", "true"); setPermanent("windowedpos", Common::Point(50, 50)); setPermanent("display", 0); - setPermanent("palette", "standard"); - setPermanent("phase_ntsc", "26.2"); - setPermanent("phase_pal", "31.3"); + setPermanent("palette", PaletteHandler::SETTING_STANDARD); setPermanent("uimessages", "true"); // TIA specific options @@ -64,12 +63,14 @@ Settings::Settings() setPermanent("tv.phosphor", "byrom"); setPermanent("tv.phosblend", "50"); setPermanent("tv.scanlines", "25"); - // TV options when using 'custom' mode + setPermanent("tv.phase_ntsc", "26.2"); + setPermanent("tv.phase_pal", "31.3"); setPermanent("tv.contrast", "0.0"); setPermanent("tv.brightness", "0.0"); setPermanent("tv.hue", "0.0"); setPermanent("tv.saturation", "0.0"); setPermanent("tv.gamma", "0.0"); + // TV options when using 'custom' mode setPermanent("tv.sharpness", "0.0"); setPermanent("tv.resolution", "0.0"); setPermanent("tv.artifacts", "0.0"); @@ -358,8 +359,11 @@ void Settings::validate() else if(i > 10) setValue("ssinterval", "10"); s = getString("palette"); - if(s != "standard" && s != "z26" && s != "user" && s != "custom") - setValue("palette", "standard"); + if(s != PaletteHandler::SETTING_STANDARD + && s != PaletteHandler::SETTING_Z26 + && s != PaletteHandler::SETTING_USER + && s != PaletteHandler::SETTING_CUSTOM) + setValue("palette", PaletteHandler::SETTING_STANDARD); s = getString("launcherfont"); if(s != "small" && s != "low_medium" && s != "medium" && s != "large" diff --git a/src/emucore/TIASurface.cxx b/src/emucore/TIASurface.cxx index a13a9fd83..8ff9f3e17 100644 --- a/src/emucore/TIASurface.cxx +++ b/src/emucore/TIASurface.cxx @@ -23,6 +23,7 @@ #include "Console.hxx" #include "TIA.hxx" #include "PNGLibrary.hxx" +#include "PaletteHandler.hxx" #include "TIASurface.hxx" namespace { @@ -76,6 +77,14 @@ TIASurface::TIASurface(OSystem& system) // Enable/disable threading in the NTSC TV effects renderer myNTSCFilter.enableThreading(myOSystem.settings().getBool("threads")); + + myPaletteHandler = make_unique(myOSystem); + myPaletteHandler->loadConfig(myOSystem.settings()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TIASurface::~TIASurface() +{ } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -89,6 +98,8 @@ void TIASurface::initialize(const Console& console, mySLineSurface->setDstPos(mode.image.x(), mode.image.y()); mySLineSurface->setDstSize(mode.image.w(), mode.image.h()); + myPaletteHandler->setPalette(); + // Phosphor mode can be enabled either globally or per-ROM int p_blend = 0; bool enable = false; @@ -188,6 +199,32 @@ void TIASurface::setNTSC(NTSCFilter::Preset preset, bool show) if(show) myFB.showMessage(buf.str()); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIASurface::changeNTSC(bool next, bool show) +{ + constexpr NTSCFilter::Preset PRESETS[] = { + NTSCFilter::Preset::OFF, NTSCFilter::Preset::RGB, NTSCFilter::Preset::SVIDEO, + NTSCFilter::Preset::COMPOSITE, NTSCFilter::Preset::BAD, NTSCFilter::Preset::CUSTOM + }; + int preset = myOSystem.settings().getInt("tv.filter"); + + if(next) + { + if(preset == int(NTSCFilter::Preset::CUSTOM)) + preset = int(NTSCFilter::Preset::OFF); + else + preset++; + } + else + { + if(preset == int(NTSCFilter::Preset::OFF)) + preset = int(NTSCFilter::Preset::CUSTOM); + else + preset--; + } + setNTSC(PRESETS[preset], show); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TIASurface::setScanlineIntensity(int amount) { diff --git a/src/emucore/TIASurface.hxx b/src/emucore/TIASurface.hxx index c87ddc881..b2c00f912 100644 --- a/src/emucore/TIASurface.hxx +++ b/src/emucore/TIASurface.hxx @@ -22,6 +22,7 @@ class TIA; class Console; class OSystem; class FBSurface; +class PaletteHandler; #include @@ -48,6 +49,7 @@ class TIASurface Creates a new TIASurface object */ explicit TIASurface(OSystem& system); + virtual ~TIASurface(); /** Set the TIA object, which is needed for actually rendering the TIA image. @@ -87,6 +89,16 @@ class TIASurface */ void setNTSC(NTSCFilter::Preset preset, bool show = true); + /** + Switch to next/previous NTSC filtering effect. + */ + void changeNTSC(bool next, bool show = true); + + /** + Retrieve palette handler. + */ + PaletteHandler& paletteHandler() const { return *myPaletteHandler; } + /** Increase/decrease current scanline intensity by given relative amount. */ @@ -100,7 +112,6 @@ class TIASurface @return New current intensity */ uInt32 enableScanlines(int relative, int absolute = 50); - void enableScanlineInterpolation(bool enable); /** Enable/disable/query phosphor effect. @@ -183,6 +194,9 @@ class TIASurface // Flag for saving a snapshot bool mySaveSnapFlag{false}; + // The palette handler + unique_ptrmyPaletteHandler; + private: // Following constructors and assignment operators not supported TIASurface() = delete; diff --git a/src/emucore/Thumbulator.cxx b/src/emucore/Thumbulator.cxx index c5bd3e637..2984159cd 100644 --- a/src/emucore/Thumbulator.cxx +++ b/src/emucore/Thumbulator.cxx @@ -108,6 +108,7 @@ void Thumbulator::setConsoleTiming(ConsoleTiming timing) case ConsoleTiming::ntsc: timing_factor = NTSC; break; case ConsoleTiming::secam: timing_factor = SECAM; break; case ConsoleTiming::pal: timing_factor = PAL; break; + default: break; // satisfy compiler } } diff --git a/src/gui/AudioDialog.cxx b/src/gui/AudioDialog.cxx deleted file mode 100644 index 1f97c2f8b..000000000 --- a/src/gui/AudioDialog.cxx +++ /dev/null @@ -1,353 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#include - -#include "bspf.hxx" - -#include "Console.hxx" -#include "Cart.hxx" -#include "CartDPC.hxx" -#include "Control.hxx" -#include "Dialog.hxx" -#include "Font.hxx" -#include "Menu.hxx" -#include "OSystem.hxx" -#include "PopUpWidget.hxx" -#include "Settings.hxx" -#include "Sound.hxx" -#include "Widget.hxx" -#include "AudioSettings.hxx" - -#include "AudioDialog.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -AudioDialog::AudioDialog(OSystem& osystem, DialogContainer& parent, - const GUI::Font& font) - : Dialog(osystem, parent, font, "Audio settings") -{ - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(); - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - const int VGAP = fontHeight / 4; - - int xpos, ypos; - int lwidth = font.getStringWidth("Volume "), - pwidth; - - WidgetArray wid; - VariantList items; - - // Set real dimensions - _w = 48 * fontWidth + HBORDER * 2; - _h = 12 * (lineHeight + VGAP) + VBORDER + _th; - - xpos = HBORDER; ypos = VBORDER + _th; - - // Enable sound - mySoundEnableCheckbox = new CheckboxWidget(this, font, xpos, ypos, - "Enable sound", kSoundEnableChanged); - wid.push_back(mySoundEnableCheckbox); - ypos += lineHeight + VGAP; - xpos += CheckboxWidget::prefixSize(font); - - // Volume - myVolumeSlider = new SliderWidget(this, font, xpos, ypos, - "Volume", lwidth, 0, 4 * fontWidth, "%"); - myVolumeSlider->setMinValue(1); myVolumeSlider->setMaxValue(100); - myVolumeSlider->setTickmarkIntervals(4); - wid.push_back(myVolumeSlider); - ypos += lineHeight + VGAP; - - // Mode - items.clear(); - VarList::push_back(items, "Low quality, medium lag", static_cast(AudioSettings::Preset::lowQualityMediumLag)); - VarList::push_back(items, "High quality, medium lag", static_cast(AudioSettings::Preset::highQualityMediumLag)); - VarList::push_back(items, "High quality, low lag", static_cast(AudioSettings::Preset::highQualityLowLag)); - VarList::push_back(items, "Ultra quality, minimal lag", static_cast(AudioSettings::Preset::ultraQualityMinimalLag)); - VarList::push_back(items, "Custom", static_cast(AudioSettings::Preset::custom)); - myModePopup = new PopUpWidget(this, font, xpos, ypos, - font.getStringWidth("Ultry quality, minimal lag"), lineHeight, - items, "Mode", lwidth, kModeChanged); - wid.push_back(myModePopup); - ypos += lineHeight + VGAP; - xpos += INDENT; - - // Fragment size - pwidth = font.getStringWidth("512 samples") + 7; - lwidth = font.getStringWidth("Resampling quality "); - items.clear(); - VarList::push_back(items, "128 samples", 128); - VarList::push_back(items, "256 samples", 256); - VarList::push_back(items, "512 samples", 512); - VarList::push_back(items, "1k samples", 1024); - VarList::push_back(items, "2k samples", 2048); - VarList::push_back(items, "4K samples", 4096); - myFragsizePopup = new PopUpWidget(this, font, xpos, ypos, - pwidth, lineHeight, - items, "Fragment size", lwidth); - wid.push_back(myFragsizePopup); - ypos += lineHeight + VGAP; - - // Output frequency - items.clear(); - VarList::push_back(items, "44100 Hz", 44100); - VarList::push_back(items, "48000 Hz", 48000); - VarList::push_back(items, "96000 Hz", 96000); - myFreqPopup = new PopUpWidget(this, font, xpos, ypos, - pwidth, lineHeight, - items, "Sample rate", lwidth); - wid.push_back(myFreqPopup); - ypos += lineHeight + VGAP; - - // Resampling quality - items.clear(); - VarList::push_back(items, "Low", static_cast(AudioSettings::ResamplingQuality::nearestNeightbour)); - VarList::push_back(items, "High", static_cast(AudioSettings::ResamplingQuality::lanczos_2)); - VarList::push_back(items, "Ultra", static_cast(AudioSettings::ResamplingQuality::lanczos_3)); - myResamplingPopup = new PopUpWidget(this, font, xpos, ypos, - pwidth, lineHeight, - items, "Resampling quality ", lwidth); - wid.push_back(myResamplingPopup); - ypos += lineHeight + VGAP; - - // Param 1 - int swidth = pwidth+23; - myHeadroomSlider = new SliderWidget(this, font, xpos, ypos, swidth, lineHeight, - "Headroom ", 0, kHeadroomChanged, 10 * fontWidth); - myHeadroomSlider->setMinValue(0); myHeadroomSlider->setMaxValue(AudioSettings::MAX_HEADROOM); - myHeadroomSlider->setTickmarkIntervals(5); - wid.push_back(myHeadroomSlider); - ypos += lineHeight + VGAP; - - // Param 2 - myBufferSizeSlider = new SliderWidget(this, font, xpos, ypos, swidth, lineHeight, - "Buffer size ", 0, kBufferSizeChanged, 10 * fontWidth); - myBufferSizeSlider->setMinValue(0); myBufferSizeSlider->setMaxValue(AudioSettings::MAX_BUFFER_SIZE); - myBufferSizeSlider->setTickmarkIntervals(5); - wid.push_back(myBufferSizeSlider); - ypos += lineHeight + VGAP; - - // Stereo sound - xpos -= INDENT; - myStereoSoundCheckbox = new CheckboxWidget(this, font, xpos, ypos, - "Stereo for all ROMs"); - wid.push_back(myStereoSoundCheckbox); - ypos += lineHeight + VGAP; - - myDpcPitch = new SliderWidget(this, font, xpos, ypos, swidth - 16, lineHeight, - "Pitfall II music pitch ", 0, 0, 5 * fontWidth); - myDpcPitch->setMinValue(10000); myDpcPitch->setMaxValue(30000); - myDpcPitch->setStepValue(100); - myDpcPitch->setTickmarkIntervals(2); - wid.push_back(myDpcPitch); - - // Add Defaults, OK and Cancel buttons - addDefaultsOKCancelBGroup(wid, font); - - addToFocusList(wid); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::loadConfig() -{ - AudioSettings& audioSettings = instance().audioSettings(); - - // Enable sound - mySoundEnableCheckbox->setState(audioSettings.enabled()); - - // Volume - myVolumeSlider->setValue(audioSettings.volume()); - - // Stereo - myStereoSoundCheckbox->setState(audioSettings.stereo()); - - // DPC Pitch - myDpcPitch->setValue(audioSettings.dpcPitch()); - - // Preset / mode - myModePopup->setSelected(static_cast(audioSettings.preset())); - - updateSettingsWithPreset(instance().audioSettings()); - - updateEnabledState(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::updateSettingsWithPreset(AudioSettings& audioSettings) -{ - // Fragsize - myFragsizePopup->setSelected(audioSettings.fragmentSize()); - - // Output frequency - myFreqPopup->setSelected(audioSettings.sampleRate()); - - // Headroom - myHeadroomSlider->setValue(audioSettings.headroom()); - - // Buffer size - myBufferSizeSlider->setValue(audioSettings.bufferSize()); - - // Resampling quality - myResamplingPopup->setSelected(static_cast(audioSettings.resamplingQuality())); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::saveConfig() -{ - AudioSettings& audioSettings = instance().audioSettings(); - - // Enabled - audioSettings.setEnabled(mySoundEnableCheckbox->getState()); - instance().sound().setEnabled(mySoundEnableCheckbox->getState()); - - // Volume - audioSettings.setVolume(myVolumeSlider->getValue()); - instance().sound().setVolume(myVolumeSlider->getValue()); - - // Stereo - audioSettings.setStereo(myStereoSoundCheckbox->getState()); - - // DPC Pitch - audioSettings.setDpcPitch(myDpcPitch->getValue()); - // update if current cart is Pitfall II - if (instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC") - { - CartridgeDPC& cart = static_cast(instance().console().cartridge()); - cart.setDpcPitch(myDpcPitch->getValue()); - } - - AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); - audioSettings.setPreset(preset); - - if (preset == AudioSettings::Preset::custom) { - // Fragsize - audioSettings.setFragmentSize(myFragsizePopup->getSelectedTag().toInt()); - audioSettings.setSampleRate(myFreqPopup->getSelectedTag().toInt()); - audioSettings.setHeadroom(myHeadroomSlider->getValue()); - audioSettings.setBufferSize(myBufferSizeSlider->getValue()); - audioSettings.setResamplingQuality(static_cast(myResamplingPopup->getSelectedTag().toInt())); - } - - // Only force a re-initialization when necessary, since it can - // be a time-consuming operation - if(instance().hasConsole()) - instance().console().initializeAudio(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::setDefaults() -{ - mySoundEnableCheckbox->setState(AudioSettings::DEFAULT_ENABLED); - myVolumeSlider->setValue(AudioSettings::DEFAULT_VOLUME); - myStereoSoundCheckbox->setState(AudioSettings::DEFAULT_STEREO); - myDpcPitch->setValue(AudioSettings::DEFAULT_DPC_PITCH); - myModePopup->setSelected(static_cast(AudioSettings::DEFAULT_PRESET)); - - if (AudioSettings::DEFAULT_PRESET == AudioSettings::Preset::custom) { - myResamplingPopup->setSelected(static_cast(AudioSettings::DEFAULT_RESAMPLING_QUALITY)); - myFragsizePopup->setSelected(AudioSettings::DEFAULT_FRAGMENT_SIZE); - myFreqPopup->setSelected(AudioSettings::DEFAULT_SAMPLE_RATE); - myHeadroomSlider->setValue(AudioSettings::DEFAULT_HEADROOM); - myBufferSizeSlider->setValue(AudioSettings::DEFAULT_BUFFER_SIZE); - } - else updatePreset(); - - updateEnabledState(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::updateEnabledState() -{ - bool active = mySoundEnableCheckbox->getState(); - AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); - bool userMode = preset == AudioSettings::Preset::custom; - - myVolumeSlider->setEnabled(active); - myStereoSoundCheckbox->setEnabled(active); - myModePopup->setEnabled(active); - // enable only for Pitfall II cart - myDpcPitch->setEnabled(active && instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC"); - - myFragsizePopup->setEnabled(active && userMode); - myFreqPopup->setEnabled(active && userMode); - myResamplingPopup->setEnabled(active && userMode); - myHeadroomSlider->setEnabled(active && userMode); - myBufferSizeSlider->setEnabled(active && userMode); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::updatePreset() -{ - AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); - - // Make a copy that does not affect the actual settings... - AudioSettings audioSettings = instance().audioSettings(); - audioSettings.setPersistent(false); - // ... and set the requested preset - audioSettings.setPreset(preset); - - updateSettingsWithPreset(audioSettings); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::handleCommand(CommandSender* sender, int cmd, - int data, int id) -{ - switch(cmd) - { - case GuiObject::kOKCmd: - saveConfig(); - close(); - break; - - case GuiObject::kDefaultsCmd: - setDefaults(); - break; - - case kSoundEnableChanged: - updateEnabledState(); - break; - - case kModeChanged: - updatePreset(); - updateEnabledState(); - break; - - case kHeadroomChanged: - { - std::ostringstream ss; - ss << std::fixed << std::setprecision(1) << (0.5 * myHeadroomSlider->getValue()) << " frames"; - myHeadroomSlider->setValueLabel(ss.str()); - break; - } - case kBufferSizeChanged: - { - std::ostringstream ss; - ss << std::fixed << std::setprecision(1) << (0.5 * myBufferSizeSlider->getValue()) << " frames"; - myBufferSizeSlider->setValueLabel(ss.str()); - break; - } - - default: - Dialog::handleCommand(sender, cmd, data, 0); - break; - } -} diff --git a/src/gui/AudioDialog.hxx b/src/gui/AudioDialog.hxx deleted file mode 100644 index b7aa35c65..000000000 --- a/src/gui/AudioDialog.hxx +++ /dev/null @@ -1,77 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#ifndef AUDIO_DIALOG_HXX -#define AUDIO_DIALOG_HXX - -class CommandSender; -class Dialog; -class DialogContainer; -class PopUpWidget; -class SliderWidget; -class StaticTextWidget; -class CheckboxWidget; -class OSystem; -class AudioSettings; - -#include "bspf.hxx" - -class AudioDialog : public Dialog -{ - public: - AudioDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font); - virtual ~AudioDialog() = default; - - private: - void loadConfig() override; - void saveConfig() override; - void setDefaults() override; - - void updatePreset(); - void updateEnabledState(); - void updateSettingsWithPreset(AudioSettings&); - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - private: - enum { - kSoundEnableChanged = 'ADse', - kModeChanged = 'ADmc', - kHeadroomChanged = 'ADhc', - kBufferSizeChanged = 'ADbc' - }; - - CheckboxWidget* mySoundEnableCheckbox{nullptr}; - SliderWidget* myVolumeSlider{nullptr}; - CheckboxWidget* myStereoSoundCheckbox{nullptr}; - PopUpWidget* myModePopup{nullptr}; - PopUpWidget* myFragsizePopup{nullptr}; - PopUpWidget* myFreqPopup{nullptr}; - PopUpWidget* myResamplingPopup{nullptr}; - SliderWidget* myHeadroomSlider{nullptr}; - SliderWidget* myBufferSizeSlider{nullptr}; - SliderWidget* myDpcPitch{nullptr}; - - private: - // Following constructors and assignment operators not supported - AudioDialog() = delete; - AudioDialog(const AudioDialog&) = delete; - AudioDialog(AudioDialog&&) = delete; - AudioDialog& operator=(const AudioDialog&) = delete; - AudioDialog& operator=(AudioDialog&&) = delete; -}; - -#endif diff --git a/src/gui/ColorWidget.cxx b/src/gui/ColorWidget.cxx index 6aa58a049..27f4bc3cf 100644 --- a/src/gui/ColorWidget.cxx +++ b/src/gui/ColorWidget.cxx @@ -25,9 +25,10 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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), + _framed(framed), _cmd(cmd) { _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) diff --git a/src/gui/ColorWidget.hxx b/src/gui/ColorWidget.hxx index 7691ff6ad..9169c2153 100644 --- a/src/gui/ColorWidget.hxx +++ b/src/gui/ColorWidget.hxx @@ -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}; diff --git a/src/gui/CommandDialog.cxx b/src/gui/CommandDialog.cxx index 5c734a52e..5790f7193 100644 --- a/src/gui/CommandDialog.cxx +++ b/src/gui/CommandDialog.cxx @@ -16,6 +16,7 @@ //============================================================================ #include "Console.hxx" +#include "PaletteHandler.hxx" #include "TIA.hxx" #include "Switches.hxx" #include "Dialog.hxx" @@ -203,7 +204,7 @@ void CommandDialog::handleCommand(CommandSender* sender, int cmd, break; case kPaletteCmd: - instance().console().togglePalette(); + instance().frameBuffer().tiaSurface().paletteHandler().cyclePalette(); updatePalette(); break; @@ -269,11 +270,11 @@ void CommandDialog::updatePalette() string palette, label; palette = instance().settings().getString("palette"); - if(BSPF::equalsIgnoreCase(palette, "standard")) + if(BSPF::equalsIgnoreCase(palette, PaletteHandler::SETTING_STANDARD)) label = "Stella Palette"; - else if(BSPF::equalsIgnoreCase(palette, "z26")) + else if(BSPF::equalsIgnoreCase(palette, PaletteHandler::SETTING_Z26)) label = "Z26 Palette"; - else if(BSPF::equalsIgnoreCase(palette, "user")) + else if(BSPF::equalsIgnoreCase(palette, PaletteHandler::SETTING_USER)) label = "User Palette"; else label = "Custom Palette"; diff --git a/src/gui/DeveloperDialog.cxx b/src/gui/DeveloperDialog.cxx index 5badbc513..288fb6a40 100644 --- a/src/gui/DeveloperDialog.cxx +++ b/src/gui/DeveloperDialog.cxx @@ -499,31 +499,6 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font) lineHeight, items, "Horizon ~ ", 0, kHorizonChanged); wid.push_back(myStateHorizonWidget); - xpos = HBORDER + INDENT; - ypos += lineHeight + VGAP * 2; - new StaticTextWidget(myTab, font, HBORDER, ypos + 1, - "When entering/exiting emulation:"); - ypos += lineHeight + VGAP; - mySaveOnExitGroup = new RadioButtonGroup(); - r = new RadioButtonWidget(myTab, font, xpos, ypos + 1, - "Do nothing", mySaveOnExitGroup); - wid.push_back(r); - ypos += lineHeight + VGAP; - r = new RadioButtonWidget(myTab, font, xpos, ypos + 1, - "Save current state in current slot", mySaveOnExitGroup); - wid.push_back(r); - ypos += lineHeight + VGAP; - r = new RadioButtonWidget(myTab, font, xpos, ypos + 1, - "Load/save all Time Machine states", mySaveOnExitGroup); - wid.push_back(r); - ypos += lineHeight + VGAP; - xpos = HBORDER; - - - myAutoSlotWidget = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Automatically change save state slots"); - wid.push_back(myAutoSlotWidget); - ypos += lineHeight + VGAP; - // Add message concerning usage const GUI::Font& infofont = instance().frameBuffer().infoFont(); ypos = myTab->getHeight() - fontHeight - infofont.getFontHeight() - VGAP - VBORDER; @@ -678,8 +653,6 @@ void DeveloperDialog::loadSettings(SettingsSet set) myUncompressed[set] = instance().settings().getInt(prefix + "tm.uncompressed"); myStateInterval[set] = instance().settings().getString(prefix + "tm.interval"); myStateHorizon[set] = instance().settings().getString(prefix + "tm.horizon"); - - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -871,12 +844,6 @@ void DeveloperDialog::loadConfig() // Debug colours handleDebugColours(instance().settings().getString("tia.dbgcolors")); - // Save on exit - string saveOnExit = instance().settings().getString("saveonexit"); - mySaveOnExitGroup->setSelected(saveOnExit == "all" ? 2 : saveOnExit == "current" ? 1 : 0); - // Automatically change save state slots - myAutoSlotWidget->setState(instance().settings().getBool("autoslot")); - #ifdef DEBUGGER_SUPPORT uInt32 w, h; @@ -953,13 +920,6 @@ void DeveloperDialog::saveConfig() instance().state().setRewindMode(myTimeMachineWidget->getState() ? StateManager::Mode::TimeMachine : StateManager::Mode::Off); - // Save on exit - int saveOnExit = mySaveOnExitGroup->getSelected(); - instance().settings().setValue("saveonexit", - saveOnExit == 0 ? "none" : saveOnExit == 1 ? "current" : "all"); - // Automatically change save state slots - instance().settings().setValue("autoslot", myAutoSlotWidget->getState()); - #ifdef DEBUGGER_SUPPORT // Debugger font style instance().settings().setValue("dbg.fontstyle", @@ -1050,8 +1010,6 @@ void DeveloperDialog::setDefaults() myStateHorizon[set] = devSettings ? "30s" : "10m"; setWidgetStates(set); - mySaveOnExitGroup->setSelected(0); - myAutoSlotWidget->setState(false); break; case 4: // Debugger options diff --git a/src/gui/DeveloperDialog.hxx b/src/gui/DeveloperDialog.hxx index ddee5468d..8bd84ab91 100644 --- a/src/gui/DeveloperDialog.hxx +++ b/src/gui/DeveloperDialog.hxx @@ -135,8 +135,6 @@ class DeveloperDialog : public Dialog SliderWidget* myUncompressedWidget{nullptr}; PopUpWidget* myStateIntervalWidget{nullptr}; PopUpWidget* myStateHorizonWidget{nullptr}; - RadioButtonGroup* mySaveOnExitGroup{nullptr}; - CheckboxWidget* myAutoSlotWidget{nullptr}; #ifdef DEBUGGER_SUPPORT // Debugger UI widgets diff --git a/src/gui/DialogContainer.cxx b/src/gui/DialogContainer.cxx index b60faf6d4..950d71c06 100644 --- a/src/gui/DialogContainer.cxx +++ b/src/gui/DialogContainer.cxx @@ -384,4 +384,3 @@ void DialogContainer::reset() uInt64 DialogContainer::_DOUBLE_CLICK_DELAY = 500; uInt64 DialogContainer::_REPEAT_INITIAL_DELAY = 400; uInt64 DialogContainer::_REPEAT_SUSTAIN_DELAY = 50; - diff --git a/src/gui/EmulationDialog.cxx b/src/gui/EmulationDialog.cxx new file mode 100644 index 000000000..ad86e2e60 --- /dev/null +++ b/src/gui/EmulationDialog.cxx @@ -0,0 +1,283 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "Console.hxx" +#include "FrameBuffer.hxx" +#include "RadioButtonWidget.hxx" +#include "TIASurface.hxx" + +#include "EmulationDialog.hxx" + +namespace { + // Emulation speed is a positive float that multiplies the framerate. However, the UI controls + // adjust speed in terms of a speedup factor (1/10, 1/9 .. 1/2, 1, 2, 3, .., 10). The following + // mapping and formatting functions implement this conversion. The speedup factor is represented + // by an integer value between -900 and 900 (0 means no speedup). + + constexpr int MAX_SPEED = 900; + constexpr int MIN_SPEED = -900; + constexpr int SPEED_STEP = 10; + + int mapSpeed(float speed) + { + speed = std::abs(speed); + + return BSPF::clamp( + static_cast(round(100 * (speed >= 1 ? speed - 1 : -1 / speed + 1))), + MIN_SPEED, MAX_SPEED + ); + } + + float unmapSpeed(int speed) + { + float f_speed = static_cast(speed) / 100; + + return speed < 0 ? -1 / (f_speed - 1) : 1 + f_speed; + } + + string formatSpeed(int speed) { + stringstream ss; + + ss + << std::setw(3) << std::fixed << std::setprecision(0) + << (unmapSpeed(speed) * 100); + + return ss.str(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +EmulationDialog::EmulationDialog(OSystem& osystem, DialogContainer& parent, + const GUI::Font& font, int max_w, int max_h) + : Dialog(osystem, parent, font, "Emulation settings") +{ + const int lineHeight = font.getLineHeight(), + fontHeight = font.getFontHeight(), + fontWidth = font.getMaxCharWidth(), + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; + + int xpos, ypos; + int lwidth = font.getStringWidth("Emulation speed "); + WidgetArray wid; + VariantList items; + const int swidth = fontWidth * 10; + + // Set real dimensions + _w = 37 * fontWidth + HBORDER * 2 + CheckboxWidget::prefixSize(_font); + _h = 12 * (lineHeight + VGAP) + VGAP * 7 + VBORDER * 3 + _th + buttonHeight; + + xpos = HBORDER; ypos = VBORDER + _th; + + // Speed + mySpeed = + new SliderWidget(this, _font, xpos, ypos-1, swidth, lineHeight, + "Emulation speed ", lwidth, kSpeedupChanged, fontWidth * 5, "%"); + mySpeed->setMinValue(MIN_SPEED); mySpeed->setMaxValue(MAX_SPEED); + mySpeed->setStepValue(SPEED_STEP); + mySpeed->setTickmarkIntervals(2); + wid.push_back(mySpeed); + ypos += lineHeight + VGAP; + + // Use sync to vblank + myUseVSync = new CheckboxWidget(this, _font, xpos, ypos + 1, "VSync"); + wid.push_back(myUseVSync); + ypos += lineHeight + VGAP; + + + myTurbo = new CheckboxWidget(this, _font, xpos, ypos + 1, "Turbo mode"); + wid.push_back(myTurbo); + ypos += lineHeight + VGAP * 3; + + // Use multi-threading + myUseThreads = new CheckboxWidget(this, _font, xpos, ypos + 1, "Multi-threading"); + wid.push_back(myUseThreads); + ypos += lineHeight + VGAP; + + // Skip progress load bars for SuperCharger ROMs + // Doesn't really belong here, but I couldn't find a better place for it + myFastSCBios = new CheckboxWidget(this, _font, xpos, ypos + 1, "Fast SuperCharger load"); + wid.push_back(myFastSCBios); + ypos += lineHeight + VGAP; + + // Show UI messages onscreen + myUIMessages = new CheckboxWidget(this, _font, xpos, ypos + 1, "Show UI messages"); + wid.push_back(myUIMessages); + ypos += lineHeight + VGAP; + + // Confirm dialog when exiting emulation + xpos = HBORDER; ypos += VGAP * 3; + myConfirmExitWidget = new CheckboxWidget(this, _font, xpos, ypos, "Confirm exiting emulation"); + wid.push_back(myConfirmExitWidget); + + xpos = HBORDER + INDENT; + ypos += lineHeight + VGAP * 3; + new StaticTextWidget(this, font, HBORDER, ypos + 1, + "When entering/exiting emulation:"); + ypos += lineHeight + VGAP; + mySaveOnExitGroup = new RadioButtonGroup(); + RadioButtonWidget* r; + r = new RadioButtonWidget(this, font, xpos, ypos + 1, + "Do nothing", mySaveOnExitGroup); + wid.push_back(r); + ypos += lineHeight + VGAP; + r = new RadioButtonWidget(this, font, xpos, ypos + 1, + "Save current state in current slot", mySaveOnExitGroup); + wid.push_back(r); + ypos += lineHeight + VGAP; + r = new RadioButtonWidget(this, font, xpos, ypos + 1, + "Load/save all Time Machine states", mySaveOnExitGroup); + wid.push_back(r); + ypos += lineHeight + VGAP; + xpos = HBORDER; + + + myAutoSlotWidget = new CheckboxWidget(this, font, xpos, ypos + 1, "Automatically change save state slots"); + wid.push_back(myAutoSlotWidget); + ypos += lineHeight + VGAP; + + // Add Defaults, OK and Cancel buttons + addDefaultsOKCancelBGroup(wid, font); + + addToFocusList(wid); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EmulationDialog::loadConfig() +{ + Settings& settings = instance().settings(); + + // Emulation speed + int speed = mapSpeed(settings.getFloat("speed")); + mySpeed->setValue(speed); + mySpeed->setValueLabel(formatSpeed(speed)); + + // Use sync to vertical blank + myUseVSync->setState(settings.getBool("vsync")); + + // Enable 'Turbo' mode + myTurbo->setState(settings.getBool("turbo")); + + // Show UI messages + myUIMessages->setState(settings.getBool("uimessages")); + + // Fast loading of Supercharger BIOS + myFastSCBios->setState(settings.getBool("fastscbios")); + + // Multi-threaded rendering + myUseThreads->setState(settings.getBool("threads")); + + // Confirm dialog when exiting emulation + myConfirmExitWidget->setState(settings.getBool("confirmexit")); + + // Save on exit + string saveOnExit = settings.getString("saveonexit"); + mySaveOnExitGroup->setSelected(saveOnExit == "all" ? 2 : saveOnExit == "current" ? 1 : 0); + // Automatically change save state slots + myAutoSlotWidget->setState(settings.getBool("autoslot")); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EmulationDialog::saveConfig() +{ + Settings& settings = instance().settings(); + + // Speed + const int speedup = mySpeed->getValue(); + settings.setValue("speed", unmapSpeed(speedup)); + if(instance().hasConsole()) + instance().console().initializeAudio(); + + // Use sync to vertical blank + settings.setValue("vsync", myUseVSync->getState()); + + // Enable 'Turbo' mode + settings.setValue("turbo", myTurbo->getState()); + + // Show UI messages + settings.setValue("uimessages", myUIMessages->getState()); + + // Fast loading of Supercharger BIOS + settings.setValue("fastscbios", myFastSCBios->getState()); + + // Multi-threaded rendering + settings.setValue("threads", myUseThreads->getState()); + + // Confirm dialog when exiting emulation + settings.setValue("confirmexit", myConfirmExitWidget->getState()); + + // Save on exit + int saveOnExit = mySaveOnExitGroup->getSelected(); + settings.setValue("saveonexit", + saveOnExit == 0 ? "none" : saveOnExit == 1 ? "current" : "all"); + // Automatically change save state slots + settings.setValue("autoslot", myAutoSlotWidget->getState()); + + if(instance().hasConsole()) + { + // update speed + instance().console().initializeAudio(); + // update VSync + instance().console().initializeVideo(); + + instance().frameBuffer().tiaSurface().ntsc().enableThreading(myUseThreads->getState()); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EmulationDialog::setDefaults() +{ + // speed + mySpeed->setValue(0); + myUseVSync->setState(true); + // misc + myUIMessages->setState(true); + myFastSCBios->setState(true); + myUseThreads->setState(false); + myConfirmExitWidget->setState(false); + + mySaveOnExitGroup->setSelected(0); + myAutoSlotWidget->setState(false); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EmulationDialog::handleCommand(CommandSender* sender, int cmd, + int data, int id) +{ + switch(cmd) + { + case GuiObject::kOKCmd: + saveConfig(); + close(); + break; + + case GuiObject::kDefaultsCmd: + setDefaults(); + break; + + case kSpeedupChanged: + mySpeed->setValueLabel(formatSpeed(mySpeed->getValue())); + break; + + default: + Dialog::handleCommand(sender, cmd, data, 0); + break; + } +} diff --git a/src/gui/EmulationDialog.hxx b/src/gui/EmulationDialog.hxx new file mode 100644 index 000000000..f1470d7bb --- /dev/null +++ b/src/gui/EmulationDialog.hxx @@ -0,0 +1,63 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef EMULATION_DIALOG_HXX +#define EMULATION_DIALOG_HXX + +class RadioButtonGroup; + +#include "Dialog.hxx" + +class EmulationDialog : public Dialog +{ +public: + EmulationDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, + int max_w, int max_h); + virtual ~EmulationDialog() = default; + +private: + void loadConfig() override; + void saveConfig() override; + void setDefaults() override; + + void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + +private: + SliderWidget* mySpeed{nullptr}; + CheckboxWidget* myUseVSync{nullptr}; + CheckboxWidget* myTurbo{nullptr}; + CheckboxWidget* myUIMessages{nullptr}; + CheckboxWidget* myFastSCBios{nullptr}; + CheckboxWidget* myUseThreads{nullptr}; + CheckboxWidget* myConfirmExitWidget{nullptr}; + RadioButtonGroup* mySaveOnExitGroup{nullptr}; + CheckboxWidget* myAutoSlotWidget{nullptr}; + + enum { + kSpeedupChanged = 'EDSp', + }; + +private: + // Following constructors and assignment operators not supported + EmulationDialog() = delete; + EmulationDialog(const EmulationDialog&) = delete; + EmulationDialog(EmulationDialog&&) = delete; + EmulationDialog& operator=(const EmulationDialog&) = delete; + EmulationDialog& operator=(EmulationDialog&&) = delete; +}; + +#endif diff --git a/src/gui/HelpDialog.cxx b/src/gui/HelpDialog.cxx index 5c9a6b1d3..77c01f174 100644 --- a/src/gui/HelpDialog.cxx +++ b/src/gui/HelpDialog.cxx @@ -121,7 +121,7 @@ void HelpDialog::updateStrings(uInt8 page, uInt8 lines, string& title) case 2: title = "Special commands"; ADD_EVENT(Event::FormatIncrease, "Switch between NTSC/PAL/SECAM"); - ADD_EVENT(Event::TogglePalette, "Switch palette"); + ADD_EVENT(Event::PaletteIncrease, "Switch to next palette"); ADD_EVENT(Event::TogglePhosphor, "Toggle 'phosphor' effect"); ADD_LINE(); ADD_EVENT(Event::ToggleGrabMouse, "Grab mouse (keep in window)"); diff --git a/src/gui/InputDialog.cxx b/src/gui/InputDialog.cxx index 03cedb644..c3959c742 100644 --- a/src/gui/InputDialog.cxx +++ b/src/gui/InputDialog.cxx @@ -53,7 +53,7 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent, int xpos, ypos, tabID; // Set real dimensions - setSize(50 * fontWidth + HBORDER * 2, + setSize(48 * fontWidth + PopUpWidget::dropDownWidth(_font) + HBORDER * 2, _th + VGAP * 3 + lineHeight + 13 * (lineHeight + VGAP) + VGAP * 8 + buttonHeight + VBORDER * 3, max_w, max_h); diff --git a/src/gui/OptionsDialog.cxx b/src/gui/OptionsDialog.cxx index 84ea9f605..865103822 100644 --- a/src/gui/OptionsDialog.cxx +++ b/src/gui/OptionsDialog.cxx @@ -23,8 +23,8 @@ #include "Widget.hxx" #include "Font.hxx" #include "Control.hxx" -#include "VideoDialog.hxx" -#include "AudioDialog.hxx" +#include "EmulationDialog.hxx" +#include "VideoAudioDialog.hxx" #include "InputDialog.hxx" #include "UIDialog.hxx" #include "SnapshotDialog.hxx" @@ -89,13 +89,10 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, return bw; }; - b = ADD_OD_BUTTON("Video" + ELLIPSIS, kVidCmd); + b = ADD_OD_BUTTON("Video & Audio" + ELLIPSIS, kVidCmd); wid.push_back(b); - b = ADD_OD_BUTTON("Audio" + ELLIPSIS, kAudCmd); -#ifndef SOUND_SUPPORT - b->clearFlags(Widget::FLAG_ENABLED); -#endif + b = ADD_OD_BUTTON("Emulation" + ELLIPSIS, kEmuCmd); wid.push_back(b); b = ADD_OD_BUTTON("Input" + ELLIPSIS, kInptCmd); @@ -143,8 +140,8 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, addCancelWidget(b); // Now create all the dialogs attached to each menu button - myVideoDialog = make_unique(osystem, parent, _font, max_w, max_h); - myAudioDialog = make_unique(osystem, parent, _font); + myVideoDialog = make_unique(osystem, parent, _font, max_w, max_h); + myEmulationDialog= make_unique(osystem, parent, _font, max_w, max_h); myInputDialog = make_unique(osystem, parent, _font, max_w, max_h); myUIDialog = make_unique(osystem, parent, _font, boss, max_w, max_h); mySnapshotDialog = make_unique(osystem, parent, _font, max_w, max_h); @@ -212,6 +209,10 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd, instance().eventHandler().leaveMenuMode(); break; + case kEmuCmd: + myEmulationDialog->open(); + break; + case kVidCmd: { // This dialog is resizable under certain conditions, so we need @@ -220,17 +221,12 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd, if(myVideoDialog == nullptr || myVideoDialog->shouldResize(w, h)) { - myVideoDialog = make_unique(instance(), parent(), + myVideoDialog = make_unique(instance(), parent(), instance().frameBuffer().font(), w, h); } myVideoDialog->open(); break; } - - case kAudCmd: - myAudioDialog->open(); - break; - case kInptCmd: { // This dialog is resizable under certain conditions, so we need diff --git a/src/gui/OptionsDialog.hxx b/src/gui/OptionsDialog.hxx index 3b5598693..001fad73b 100644 --- a/src/gui/OptionsDialog.hxx +++ b/src/gui/OptionsDialog.hxx @@ -22,8 +22,8 @@ class CommandSender; class DialogContainer; class GuiObject; class OSystem; -class VideoDialog; -class AudioDialog; +class EmulationDialog; +class VideoAudioDialog; class InputDialog; class UIDialog; class SnapshotDialog; @@ -52,8 +52,8 @@ class OptionsDialog : public Dialog void handleCommand(CommandSender* sender, int cmd, int data, int id) override; private: - unique_ptr myVideoDialog; - unique_ptr myAudioDialog; + unique_ptr myVideoDialog; + unique_ptr myEmulationDialog; unique_ptr myInputDialog; unique_ptr myUIDialog; unique_ptr mySnapshotDialog; @@ -78,7 +78,7 @@ class OptionsDialog : public Dialog enum { kBasSetCmd = 'BAST', kVidCmd = 'VIDO', - kAudCmd = 'AUDO', + kEmuCmd = 'EMUO', kInptCmd = 'INPT', kUsrIfaceCmd = 'URIF', kSnapCmd = 'SNAP', diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 099886b9b..eafc2e00b 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -105,12 +105,13 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, wid.push_back(myDialogFontPopup); // Enable HiDPI mode - myHidpiWidget = new CheckboxWidget(myTab, font, myDialogFontPopup->getRight() + fontWidth * 5, + xpos = myDialogFontPopup->getRight() + fontWidth * 5; + myHidpiWidget = new CheckboxWidget(myTab, font, xpos, ypos + 1, "HiDPI mode (*)"); wid.push_back(myHidpiWidget); - ypos += lineHeight + VGAP; // Dialog position + xpos = HBORDER; ypos += lineHeight + VGAP; items.clear(); VarList::push_back(items, "Centered", 0); VarList::push_back(items, "Left top", 1); @@ -120,14 +121,14 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, myPositionPopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, items, "Dialogs position", lwidth); wid.push_back(myPositionPopup); - ypos += lineHeight + VGAP * 2; - // Confirm dialog when exiting emulation - myConfirmExitWidget = new CheckboxWidget(myTab, font, xpos, ypos, "Confirm exiting emulation"); - wid.push_back(myConfirmExitWidget); - ypos += lineHeight + VGAP * 3; + // Center window (in windowed mode) + xpos = myHidpiWidget->getLeft(); + myCenter = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Center windows"); + wid.push_back(myCenter); // Delay between quick-selecting characters in ListWidget + xpos = HBORDER; ypos += lineHeight + VGAP * 4; int swidth = myPalettePopup->getWidth() - lwidth; myListDelaySlider = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight, "List input delay ", 0, kListDelay, @@ -303,6 +304,10 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, wid.clear(); addDefaultsOKCancelBGroup(wid, font); addBGroupToFocusList(wid); + +#ifndef WINDOWED_SUPPORT + myCenter->clearFlags(Widget::FLAG_ENABLED); +#endif } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -353,6 +358,10 @@ void UIDialog::loadConfig() const string& pal = settings.getString("uipalette"); myPalettePopup->setSelected(pal, "standard"); + // Dialog font + const string& dialogFont = settings.getString("dialogfont"); + myDialogFontPopup->setSelected(dialogFont, "medium"); + // Enable HiDPI mode if (!instance().frameBuffer().hidpiAllowed()) { @@ -364,16 +373,12 @@ void UIDialog::loadConfig() myHidpiWidget->setState(settings.getBool("hidpi")); } - // Confirm dialog when exiting emulation - myConfirmExitWidget->setState(settings.getBool("confirmexit")); - - // Dialog font - const string& dialogFont = settings.getString("dialogfont"); - myDialogFontPopup->setSelected(dialogFont, "medium"); - // Dialog position myPositionPopup->setSelected(settings.getString("dialogpos"), "0"); + // Center window + myCenter->setState(settings.getBool("center")); + // Listwidget quick delay int delay = settings.getInt("listdelay"); myListDelaySlider->setValue(delay); @@ -436,18 +441,18 @@ void UIDialog::saveConfig() myPalettePopup->getSelectedTag().toString()); instance().frameBuffer().setUIPalette(); - // Enable HiDPI mode - settings.setValue("hidpi", myHidpiWidget->getState()); - // Dialog font settings.setValue("dialogfont", myDialogFontPopup->getSelectedTag().toString()); + // Enable HiDPI mode + settings.setValue("hidpi", myHidpiWidget->getState()); + // Dialog position settings.setValue("dialogpos", myPositionPopup->getSelectedTag().toString()); - // Confirm dialog when exiting emulation - settings.setValue("confirmexit", myConfirmExitWidget->getState()); + // Center window + settings.setValue("center", myCenter->getState()); // Listwidget quick delay settings.setValue("listdelay", myListDelaySlider->getValue()); @@ -481,10 +486,10 @@ void UIDialog::setDefaults() { case 0: // Misc. options myPalettePopup->setSelected("standard"); - myHidpiWidget->setState(false); myDialogFontPopup->setSelected("medium", ""); + myHidpiWidget->setState(false); myPositionPopup->setSelected("0"); - myConfirmExitWidget->setState(false); + myCenter->setState(false); myListDelaySlider->setValue(300); myWheelLinesSlider->setValue(4); myDoubleClickSlider->setValue(500); diff --git a/src/gui/UIDialog.hxx b/src/gui/UIDialog.hxx index 83851e971..6ed1c655f 100644 --- a/src/gui/UIDialog.hxx +++ b/src/gui/UIDialog.hxx @@ -66,10 +66,10 @@ class UIDialog : public Dialog, public CommandSender // Misc options PopUpWidget* myPalettePopup{nullptr}; - CheckboxWidget* myHidpiWidget{nullptr}; PopUpWidget* myDialogFontPopup{nullptr}; + CheckboxWidget* myHidpiWidget{nullptr}; PopUpWidget* myPositionPopup{nullptr}; - CheckboxWidget* myConfirmExitWidget{nullptr}; + CheckboxWidget* myCenter{nullptr}; SliderWidget* myListDelaySlider{nullptr}; SliderWidget* myWheelLinesSlider{nullptr}; SliderWidget* myControllerRateSlider{nullptr}; diff --git a/src/gui/VideoAudioDialog.cxx b/src/gui/VideoAudioDialog.cxx new file mode 100644 index 000000000..5d569014a --- /dev/null +++ b/src/gui/VideoAudioDialog.cxx @@ -0,0 +1,1084 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include + +#include "bspf.hxx" +#include "Base.hxx" +#include "Control.hxx" +#include "Cart.hxx" +#include "CartDPC.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" +#include "Settings.hxx" +#include "Sound.hxx" +#include "AudioSettings.hxx" +#include "Widget.hxx" +#include "Font.hxx" +#include "TabWidget.hxx" +#include "NTSCFilter.hxx" +#include "TIASurface.hxx" + +#include "VideoAudioDialog.hxx" + +#define CREATE_CUSTOM_SLIDERS(obj, desc, cmd) \ + myTV ## obj = \ + new SliderWidget(myTab, _font, xpos, ypos-1, swidth, lineHeight, \ + desc, lwidth, cmd, fontWidth*4, "%"); \ + myTV ## obj->setMinValue(0); myTV ## obj->setMaxValue(100); \ + myTV ## obj->setStepValue(2); \ + myTV ## obj->setTickmarkIntervals(2); \ + wid.push_back(myTV ## obj); \ + ypos += lineHeight + VGAP; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +VideoAudioDialog::VideoAudioDialog(OSystem& osystem, DialogContainer& parent, + const GUI::Font& font, int max_w, int max_h) + : Dialog(osystem, parent, font, "Video & Audio settings") +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(), + buttonHeight = _font.getLineHeight() * 1.25; + const int VGAP = fontHeight / 4; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + int xpos, ypos; + + // Set real dimensions + setSize(44 * fontWidth + HBORDER * 2 + PopUpWidget::dropDownWidth(font) * 2, + _th + VGAP * 6 + lineHeight + 10 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3, + max_w, max_h); + + // The tab widget + xpos = 2; ypos = VGAP; + myTab = new TabWidget(this, font, xpos, ypos + _th, + _w - 2*xpos, + _h - _th - VGAP - buttonHeight - VBORDER * 2); + addTabWidget(myTab); + + addDisplayTab(); + addPaletteTab(); + addTVEffectsTab(); + addAudioTab(); + + //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); + addBGroupToFocusList(wid); + + // Activate the first tab + myTab->setActiveTab(0); + + // Disable certain functions when we know they aren't present +#ifndef WINDOWED_SUPPORT + myFullscreen->clearFlags(Widget::FLAG_ENABLED); + myUseStretch->clearFlags(Widget::FLAG_ENABLED); + myTVOverscan->clearFlags(Widget::FLAG_ENABLED); +#endif +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addDisplayTab() +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VGAP = fontHeight / 4; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = CheckboxWidget::prefixSize(_font); + const int lwidth = _font.getStringWidth("V-Size adjust "), + pwidth = _font.getStringWidth("OpenGLES2"); + int xpos = HBORDER, + ypos = VBORDER; + WidgetArray wid; + VariantList items; + const int tabID = myTab->addTab(" Display ", TabWidget::AUTO_WIDTH); + + // Video renderer + myRenderer = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight, + instance().frameBuffer().supportedRenderers(), + "Renderer ", lwidth); + wid.push_back(myRenderer); + const int swidth = myRenderer->getWidth() - lwidth; + ypos += lineHeight + VGAP; + + // TIA interpolation + myTIAInterpolate = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Interpolation "); + wid.push_back(myTIAInterpolate); ypos += lineHeight + VGAP * 4; + + // TIA zoom levels (will be dynamically filled later) + myTIAZoom = new SliderWidget(myTab, _font, xpos, ypos - 1, swidth, lineHeight, + "Zoom ", lwidth, 0, fontWidth * 4, "%"); + myTIAZoom->setMinValue(200); myTIAZoom->setStepValue(FrameBuffer::ZOOM_STEPS * 100); + wid.push_back(myTIAZoom); + ypos += lineHeight + VGAP; + + // Fullscreen + myFullscreen = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Fullscreen", kFullScreenChanged); + wid.push_back(myFullscreen); + ypos += lineHeight + VGAP; + + /*pwidth = font.getStringWidth("0: 3840x2860@120Hz"); + myFullScreenMode = new PopUpWidget(myTab, font, xpos + INDENT + 2, ypos, pwidth, lineHeight, + instance().frameBuffer().supportedScreenModes(), "Mode "); + wid.push_back(myFullScreenMode); + ypos += lineHeight + VGAP;*/ + + // FS stretch + myUseStretch = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Stretch"); + wid.push_back(myUseStretch); + ypos += lineHeight + VGAP; + + // FS overscan + myTVOverscan = new SliderWidget(myTab, _font, xpos + INDENT, ypos - 1, swidth, lineHeight, + "Overscan", lwidth - INDENT, kOverscanChanged, fontWidth * 3, "%"); + myTVOverscan->setMinValue(0); myTVOverscan->setMaxValue(10); + myTVOverscan->setTickmarkIntervals(2); + wid.push_back(myTVOverscan); + ypos += lineHeight + VGAP; + + // Vertical size + myVSizeAdjust = + new SliderWidget(myTab, _font, xpos, ypos-1, swidth, lineHeight, + "V-Size adjust", lwidth, kVSizeChanged, fontWidth * 7, "%", 0, true); + myVSizeAdjust->setMinValue(-5); myVSizeAdjust->setMaxValue(5); + myVSizeAdjust->setTickmarkIntervals(2); + wid.push_back(myVSizeAdjust); + + // Add items for tab 0 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addPaletteTab() +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; + const int lwidth = _font.getStringWidth(" NTSC phase "); + const int pwidth = _font.getStringWidth("Standard"); + int xpos = HBORDER, + ypos = VBORDER; + WidgetArray wid; + VariantList items; + const int tabID = myTab->addTab(" Palettes ", TabWidget::AUTO_WIDTH); + + // TIA Palette + items.clear(); + VarList::push_back(items, "Standard", PaletteHandler::SETTING_STANDARD); + VarList::push_back(items, "z26", PaletteHandler::SETTING_Z26); + if (instance().checkUserPalette()) + VarList::push_back(items, "User", PaletteHandler::SETTING_USER); + VarList::push_back(items, "Custom", PaletteHandler::SETTING_CUSTOM); + myTIAPalette = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, + lineHeight, items, "Palette ", lwidth, kPaletteChanged); + wid.push_back(myTIAPalette); + ypos += lineHeight + VGAP; + + const int swidth = myTIAPalette->getWidth() - lwidth; + const int plWidth = _font.getStringWidth("NTSC phase "); + const int pswidth = swidth - INDENT + lwidth - plWidth; + + myPhaseShiftNtsc = + new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight, + "NTSC phase", plWidth, kNtscShiftChanged, fontWidth * 5); + 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; + + myPhaseShiftPal = + new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight, + "PAL phase", plWidth, kPalShiftChanged, fontWidth * 5); + 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; + + 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 + xpos = myPhaseShiftNtsc->getRight() + fontWidth * 2; + addPalette(xpos, VBORDER, _w - 2 * 2 - HBORDER - xpos, + myTVGamma->getBottom() - myTIAPalette->getTop()); + + // Add items for tab 2 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addTVEffectsTab() +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(), + buttonHeight = _font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = CheckboxWidget::prefixSize(_font);// fontWidth * 2; + const int VGAP = fontHeight / 4; + int xpos = HBORDER, + ypos = VBORDER; + const int lwidth = _font.getStringWidth("Saturation "); + const int pwidth = _font.getStringWidth("Bad adjust "); + WidgetArray wid; + VariantList items; + const int tabID = myTab->addTab(" TV Effects ", TabWidget::AUTO_WIDTH); + + items.clear(); + VarList::push_back(items, "Disabled", static_cast(NTSCFilter::Preset::OFF)); + VarList::push_back(items, "RGB", static_cast(NTSCFilter::Preset::RGB)); + VarList::push_back(items, "S-Video", static_cast(NTSCFilter::Preset::SVIDEO)); + VarList::push_back(items, "Composite", static_cast(NTSCFilter::Preset::COMPOSITE)); + VarList::push_back(items, "Bad adjust", static_cast(NTSCFilter::Preset::BAD)); + VarList::push_back(items, "Custom", static_cast(NTSCFilter::Preset::CUSTOM)); + myTVMode = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight, + items, "TV mode ", 0, kTVModeChanged); + wid.push_back(myTVMode); + ypos += lineHeight + VGAP; + + // Custom adjustables (using macro voodoo) + const int swidth = myTVMode->getWidth() - INDENT - lwidth; + xpos += INDENT; + + CREATE_CUSTOM_SLIDERS(Sharp, "Sharpness ", 0) + CREATE_CUSTOM_SLIDERS(Res, "Resolution ", 0) + CREATE_CUSTOM_SLIDERS(Artifacts, "Artifacts ", 0) + CREATE_CUSTOM_SLIDERS(Fringe, "Fringing ", 0) + CREATE_CUSTOM_SLIDERS(Bleed, "Bleeding ", 0) + + ypos += VGAP * 3; + + xpos = HBORDER; + + // TV Phosphor effect + myTVPhosphor = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Phosphor for all ROMs", kPhosphorChanged); + wid.push_back(myTVPhosphor); + ypos += lineHeight + VGAP / 2; + + // TV Phosphor blend level + xpos += INDENT; + CREATE_CUSTOM_SLIDERS(PhosLevel, "Blend", kPhosBlendChanged) + ypos += VGAP; + + // Scanline intensity and interpolation + xpos -= INDENT; + myTVScanLabel = new StaticTextWidget(myTab, _font, xpos, ypos, "Scanlines:"); + ypos += lineHeight + VGAP / 2; + + xpos += INDENT; + CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity", kScanlinesChanged) + + // Create buttons in 2nd column + xpos = myTVSharp->getRight() + fontWidth * 2; + ypos = VBORDER - VGAP / 2; + + // Adjustable presets + int cloneWidth = _font.getStringWidth("Clone Bad Adjust") + fontWidth * 2.5; +#define CREATE_CLONE_BUTTON(obj, desc) \ + myClone ## obj = \ + new ButtonWidget(myTab, _font, xpos, ypos, cloneWidth, buttonHeight,\ + desc, kClone ## obj ##Cmd); \ + wid.push_back(myClone ## obj); \ + ypos += buttonHeight + VGAP; + + ypos += VGAP; + CREATE_CLONE_BUTTON(RGB, "Clone RGB") + CREATE_CLONE_BUTTON(Svideo, "Clone S-Video") + CREATE_CLONE_BUTTON(Composite, "Clone Composite") + CREATE_CLONE_BUTTON(Bad, "Clone Bad adjust") + CREATE_CLONE_BUTTON(Custom, "Revert") + + // Add items for tab 3 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addAudioTab() +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = CheckboxWidget::prefixSize(_font); + const int VGAP = fontHeight / 4; + + int xpos, ypos; + int lwidth = _font.getStringWidth("Volume "), + pwidth; + WidgetArray wid; + VariantList items; + const int tabID = myTab->addTab(" Audio ", TabWidget::AUTO_WIDTH); + + xpos = HBORDER; ypos = VBORDER; + + // Enable sound + mySoundEnableCheckbox = new CheckboxWidget(myTab, _font, xpos, ypos, + "Enable sound", kSoundEnableChanged); + wid.push_back(mySoundEnableCheckbox); + ypos += lineHeight + VGAP; + xpos += CheckboxWidget::prefixSize(_font); + + // Volume + myVolumeSlider = new SliderWidget(myTab, _font, xpos, ypos, + "Volume", lwidth, 0, 4 * fontWidth, "%"); + myVolumeSlider->setMinValue(1); myVolumeSlider->setMaxValue(100); + myVolumeSlider->setTickmarkIntervals(4); + wid.push_back(myVolumeSlider); + ypos += lineHeight + VGAP; + + // Mode + items.clear(); + VarList::push_back(items, "Low quality, medium lag", static_cast(AudioSettings::Preset::lowQualityMediumLag)); + VarList::push_back(items, "High quality, medium lag", static_cast(AudioSettings::Preset::highQualityMediumLag)); + VarList::push_back(items, "High quality, low lag", static_cast(AudioSettings::Preset::highQualityLowLag)); + VarList::push_back(items, "Ultra quality, minimal lag", static_cast(AudioSettings::Preset::ultraQualityMinimalLag)); + VarList::push_back(items, "Custom", static_cast(AudioSettings::Preset::custom)); + myModePopup = new PopUpWidget(myTab, _font, xpos, ypos, + _font.getStringWidth("Ultry quality, minimal lag"), lineHeight, + items, "Mode", lwidth, kModeChanged); + wid.push_back(myModePopup); + ypos += lineHeight + VGAP; + xpos += INDENT; + + // Fragment size + lwidth = _font.getStringWidth("Resampling quality "); + pwidth = myModePopup->getRight() - xpos - lwidth - PopUpWidget::dropDownWidth(_font); + items.clear(); + VarList::push_back(items, "128 samples", 128); + VarList::push_back(items, "256 samples", 256); + VarList::push_back(items, "512 samples", 512); + VarList::push_back(items, "1k samples", 1024); + VarList::push_back(items, "2k samples", 2048); + VarList::push_back(items, "4K samples", 4096); + myFragsizePopup = new PopUpWidget(myTab, _font, xpos, ypos, + pwidth, lineHeight, + items, "Fragment size", lwidth); + wid.push_back(myFragsizePopup); + ypos += lineHeight + VGAP; + + // Output frequency + items.clear(); + VarList::push_back(items, "44100 Hz", 44100); + VarList::push_back(items, "48000 Hz", 48000); + VarList::push_back(items, "96000 Hz", 96000); + myFreqPopup = new PopUpWidget(myTab, _font, xpos, ypos, + pwidth, lineHeight, + items, "Sample rate", lwidth); + wid.push_back(myFreqPopup); + ypos += lineHeight + VGAP; + + // Resampling quality + items.clear(); + VarList::push_back(items, "Low", static_cast(AudioSettings::ResamplingQuality::nearestNeightbour)); + VarList::push_back(items, "High", static_cast(AudioSettings::ResamplingQuality::lanczos_2)); + VarList::push_back(items, "Ultra", static_cast(AudioSettings::ResamplingQuality::lanczos_3)); + myResamplingPopup = new PopUpWidget(myTab, _font, xpos, ypos, + pwidth, lineHeight, + items, "Resampling quality ", lwidth); + wid.push_back(myResamplingPopup); + ypos += lineHeight + VGAP; + + // Param 1 + int swidth = pwidth + PopUpWidget::dropDownWidth(_font); + myHeadroomSlider = new SliderWidget(myTab, _font, xpos, ypos, swidth, lineHeight, + "Headroom ", 0, kHeadroomChanged, 10 * fontWidth); + myHeadroomSlider->setMinValue(0); myHeadroomSlider->setMaxValue(AudioSettings::MAX_HEADROOM); + myHeadroomSlider->setTickmarkIntervals(5); + wid.push_back(myHeadroomSlider); + ypos += lineHeight + VGAP; + + // Param 2 + myBufferSizeSlider = new SliderWidget(myTab, _font, xpos, ypos, swidth, lineHeight, + "Buffer size ", 0, kBufferSizeChanged, 10 * fontWidth); + myBufferSizeSlider->setMinValue(0); myBufferSizeSlider->setMaxValue(AudioSettings::MAX_BUFFER_SIZE); + myBufferSizeSlider->setTickmarkIntervals(5); + wid.push_back(myBufferSizeSlider); + ypos += lineHeight + VGAP; + + // Stereo sound + xpos -= INDENT; + myStereoSoundCheckbox = new CheckboxWidget(myTab, _font, xpos, ypos, + "Stereo for all ROMs"); + wid.push_back(myStereoSoundCheckbox); + ypos += lineHeight + VGAP; + + swidth += INDENT - fontWidth * 4; + myDpcPitch = new SliderWidget(myTab, _font, xpos, ypos, swidth, lineHeight, + "Pitfall II music pitch ", 0, 0, 5 * fontWidth); + myDpcPitch->setMinValue(10000); myDpcPitch->setMaxValue(30000); + myDpcPitch->setStepValue(100); + myDpcPitch->setTickmarkIntervals(2); + wid.push_back(myDpcPitch); + + // Add items for tab 4 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::loadConfig() +{ + // Display tab + // Renderer settings + myRenderer->setSelected(instance().settings().getString("video"), "default"); + + // TIA interpolation + myTIAInterpolate->setState(instance().settings().getBool("tia.inter")); + + // TIA zoom levels + // These are dynamically loaded, since they depend on the size of + // the desktop and which renderer we're using + float minZoom = instance().frameBuffer().supportedTIAMinZoom(); // or 2 if we allow lower values + float maxZoom = instance().frameBuffer().supportedTIAMaxZoom(); + + myTIAZoom->setMinValue(minZoom * 100); + myTIAZoom->setMaxValue(maxZoom * 100); + myTIAZoom->setTickmarkIntervals((maxZoom - minZoom) * 2); // every ~50% + myTIAZoom->setValue(instance().settings().getFloat("tia.zoom") * 100); + + // Fullscreen + myFullscreen->setState(instance().settings().getBool("fullscreen")); + /*string mode = instance().settings().getString("fullscreenmode"); + myFullScreenMode->setSelected(mode);*/ + // Fullscreen stretch setting + myUseStretch->setState(instance().settings().getBool("tia.fs_stretch")); + // Fullscreen overscan setting + myTVOverscan->setValue(instance().settings().getInt("tia.fs_overscan")); + handleFullScreenChange(); + + // Aspect ratio setting (NTSC and PAL) + myVSizeAdjust->setValue(instance().settings().getInt("tia.vsizeadjust")); + + ///////////////////////////////////////////////////////////////////////////// + // Palettes tab + // TIA Palette + myPalette = instance().settings().getString("palette"); + myTIAPalette->setSelected(myPalette, PaletteHandler::SETTING_STANDARD); + + // 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(); + + ///////////////////////////////////////////////////////////////////////////// + // TV Effects tab + // TV Mode + myTVMode->setSelected( + instance().settings().getString("tv.filter"), "0"); + int preset = instance().settings().getInt("tv.filter"); + handleTVModeChange(NTSCFilter::Preset(preset)); + + // TV Custom adjustables + loadTVAdjustables(NTSCFilter::Preset::CUSTOM); + + // TV phosphor mode + myTVPhosphor->setState(instance().settings().getString("tv.phosphor") == "always"); + + // TV phosphor blend + myTVPhosLevel->setValue(instance().settings().getInt("tv.phosblend")); + handlePhosphorChange(); + + // TV scanline intensity and interpolation + myTVScanIntense->setValue(instance().settings().getInt("tv.scanlines")); + + ///////////////////////////////////////////////////////////////////////////// + // Audio tab + AudioSettings& audioSettings = instance().audioSettings(); + + // Enable sound +#ifdef SOUND_SUPPORT + mySoundEnableCheckbox->setState(audioSettings.enabled()); +#else + mySoundEnableCheckbox->setState(false); +#endif + + // Volume + myVolumeSlider->setValue(audioSettings.volume()); + + // Stereo + myStereoSoundCheckbox->setState(audioSettings.stereo()); + + // DPC Pitch + myDpcPitch->setValue(audioSettings.dpcPitch()); + + // Preset / mode + myModePopup->setSelected(static_cast(audioSettings.preset())); + + updateSettingsWithPreset(instance().audioSettings()); + + updateEnabledState(); + + myTab->loadConfig(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::updateSettingsWithPreset(AudioSettings& audioSettings) +{ + // Fragsize + myFragsizePopup->setSelected(audioSettings.fragmentSize()); + + // Output frequency + myFreqPopup->setSelected(audioSettings.sampleRate()); + + // Headroom + myHeadroomSlider->setValue(audioSettings.headroom()); + + // Buffer size + myBufferSizeSlider->setValue(audioSettings.bufferSize()); + + // Resampling quality + myResamplingPopup->setSelected(static_cast(audioSettings.resamplingQuality())); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::saveConfig() +{ + ///////////////////////////////////////////////////////////////////////////// + // Display tab + // Renderer setting + instance().settings().setValue("video", + myRenderer->getSelectedTag().toString()); + + // TIA interpolation + instance().settings().setValue("tia.inter", myTIAInterpolate->getState()); + + // Fullscreen + instance().settings().setValue("fullscreen", myFullscreen->getState()); + // Fullscreen stretch setting + instance().settings().setValue("tia.fs_stretch", myUseStretch->getState()); + // 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); + + + // Note: Palette values are saved directly when changed! + + + ///////////////////////////////////////////////////////////////////////////// + // TV Effects tab + // TV Mode + instance().settings().setValue("tv.filter", + myTVMode->getSelectedTag().toString()); + // TV Custom adjustables + NTSCFilter::Adjustable ntscAdj; + ntscAdj.sharpness = myTVSharp->getValue(); + ntscAdj.resolution = myTVRes->getValue(); + ntscAdj.artifacts = myTVArtifacts->getValue(); + ntscAdj.fringing = myTVFringe->getValue(); + ntscAdj.bleed = myTVBleed->getValue(); + instance().frameBuffer().tiaSurface().ntsc().setCustomAdjustables(ntscAdj); + + // TV phosphor mode + instance().settings().setValue("tv.phosphor", + myTVPhosphor->getState() ? "always" : "byrom"); + // TV phosphor blend + instance().settings().setValue("tv.phosblend", myTVPhosLevel->getValueLabel() == "Off" + ? "0" : myTVPhosLevel->getValueLabel()); + + // TV scanline intensity + instance().settings().setValue("tv.scanlines", myTVScanIntense->getValueLabel()); + + if(instance().hasConsole()) + { + instance().console().setTIAProperties(); + + if(vsizeChanged) + { + instance().console().tia().clearFrameBuffer(); + instance().console().initializeVideo(); + } + } + + // Finally, issue a complete framebuffer re-initialization... + instance().createFrameBuffer(); + + // ... and apply potential setting changes to the TIA surface + instance().frameBuffer().tiaSurface().updateSurfaceSettings(); + + ///////////////////////////////////////////////////////////////////////////// + // Audio tab + AudioSettings& audioSettings = instance().audioSettings(); + + // Enabled + audioSettings.setEnabled(mySoundEnableCheckbox->getState()); + instance().sound().setEnabled(mySoundEnableCheckbox->getState()); + + // Volume + audioSettings.setVolume(myVolumeSlider->getValue()); + instance().sound().setVolume(myVolumeSlider->getValue()); + + // Stereo + audioSettings.setStereo(myStereoSoundCheckbox->getState()); + + // DPC Pitch + audioSettings.setDpcPitch(myDpcPitch->getValue()); + // update if current cart is Pitfall II + if (instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC") + { + CartridgeDPC& cart = static_cast(instance().console().cartridge()); + cart.setDpcPitch(myDpcPitch->getValue()); + } + + AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); + audioSettings.setPreset(preset); + + if (preset == AudioSettings::Preset::custom) { + // Fragsize + audioSettings.setFragmentSize(myFragsizePopup->getSelectedTag().toInt()); + audioSettings.setSampleRate(myFreqPopup->getSelectedTag().toInt()); + audioSettings.setHeadroom(myHeadroomSlider->getValue()); + audioSettings.setBufferSize(myBufferSizeSlider->getValue()); + audioSettings.setResamplingQuality(static_cast(myResamplingPopup->getSelectedTag().toInt())); + } + + // Only force a re-initialization when necessary, since it can + // be a time-consuming operation + if(instance().hasConsole()) + instance().console().initializeAudio(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::setDefaults() +{ + switch(myTab->getActiveTab()) + { + case 0: // General + { + myRenderer->setSelectedIndex(0); + myTIAInterpolate->setState(false); + // screen size + myFullscreen->setState(false); + //myFullScreenMode->setSelectedIndex(0); + myUseStretch->setState(false); + myTVOverscan->setValue(0); + myTIAZoom->setValue(300); + myVSizeAdjust->setValue(0); + + handleFullScreenChange(); + break; + } + + case 1: // Palettes + myTIAPalette->setSelected(PaletteHandler::SETTING_STANDARD); + 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 + { + myTVMode->setSelected("0", "0"); + + // TV phosphor mode + myTVPhosphor->setState(false); + + // TV phosphor blend + myTVPhosLevel->setValue(50); + + // TV scanline intensity and interpolation + myTVScanIntense->setValue(25); + + // Make sure that mutually-exclusive items are not enabled at the same time + handleTVModeChange(NTSCFilter::Preset::OFF); + handlePhosphorChange(); + loadTVAdjustables(NTSCFilter::Preset::CUSTOM); + break; + } + case 3: // Audio + mySoundEnableCheckbox->setState(AudioSettings::DEFAULT_ENABLED); + myVolumeSlider->setValue(AudioSettings::DEFAULT_VOLUME); + myStereoSoundCheckbox->setState(AudioSettings::DEFAULT_STEREO); + myDpcPitch->setValue(AudioSettings::DEFAULT_DPC_PITCH); + myModePopup->setSelected(static_cast(AudioSettings::DEFAULT_PRESET)); + + if (AudioSettings::DEFAULT_PRESET == AudioSettings::Preset::custom) { + myResamplingPopup->setSelected(static_cast(AudioSettings::DEFAULT_RESAMPLING_QUALITY)); + myFragsizePopup->setSelected(AudioSettings::DEFAULT_FRAGMENT_SIZE); + myFreqPopup->setSelected(AudioSettings::DEFAULT_SAMPLE_RATE); + myHeadroomSlider->setValue(AudioSettings::DEFAULT_HEADROOM); + myBufferSizeSlider->setValue(AudioSettings::DEFAULT_BUFFER_SIZE); + } + else updatePreset(); + + updateEnabledState(); + break; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handleTVModeChange(NTSCFilter::Preset preset) +{ + bool enable = preset == NTSCFilter::Preset::CUSTOM; + + myTVSharp->setEnabled(enable); + myTVRes->setEnabled(enable); + myTVArtifacts->setEnabled(enable); + myTVFringe->setEnabled(enable); + myTVBleed->setEnabled(enable); + myCloneComposite->setEnabled(enable); + myCloneSvideo->setEnabled(enable); + myCloneRGB->setEnabled(enable); + myCloneBad->setEnabled(enable); + myCloneCustom->setEnabled(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::loadTVAdjustables(NTSCFilter::Preset preset) +{ + NTSCFilter::Adjustable adj; + instance().frameBuffer().tiaSurface().ntsc().getAdjustables( + adj, NTSCFilter::Preset(preset)); + myTVSharp->setValue(adj.sharpness); + myTVRes->setValue(adj.resolution); + myTVArtifacts->setValue(adj.artifacts); + myTVFringe->setValue(adj.fringing); + myTVBleed->setValue(adj.bleed); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handlePaletteChange() +{ + bool enable = myTIAPalette->getSelectedTag().toString() == "custom"; + + myPhaseShiftNtsc->setEnabled(enable); + myPhaseShiftPal->setEnabled(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::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 VideoAudioDialog::handleFullScreenChange() +{ + bool enable = myFullscreen->getState(); + myUseStretch->setEnabled(enable); + myTVOverscan->setEnabled(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handleOverscanChange() +{ + if (myTVOverscan->getValue() == 0) + { + myTVOverscan->setValueLabel("Off"); + myTVOverscan->setValueUnit(""); + } + else + myTVOverscan->setValueUnit("%"); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handlePhosphorChange() +{ + myTVPhosLevel->setEnabled(myTVPhosphor->getState()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handleCommand(CommandSender* sender, int cmd, + int data, int id) +{ + switch (cmd) + { + case GuiObject::kOKCmd: + saveConfig(); + 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: + { + std::ostringstream ss; + + ss << std::setw(4) << std::fixed << std::setprecision(1) + << (0.1 * abs(myPhaseShiftNtsc->getValue())) << DEGREE; + myPhaseShiftNtsc->setValueLabel(ss.str()); + handlePaletteUpdate(); + break; + } + case kPalShiftChanged: + { + std::ostringstream ss; + + ss << std::setw(4) << std::fixed << std::setprecision(1) + << (0.1 * abs(myPhaseShiftPal->getValue())) << DEGREE; + myPhaseShiftPal->setValueLabel(ss.str()); + handlePaletteUpdate(); + break; + } + case kVSizeChanged: + { + int adjust = myVSizeAdjust->getValue(); + + if (!adjust) + { + myVSizeAdjust->setValueLabel("Default"); + myVSizeAdjust->setValueUnit(""); + } + else + myVSizeAdjust->setValueUnit("%"); + break; + } + case kFullScreenChanged: + handleFullScreenChange(); + break; + + case kOverscanChanged: + handleOverscanChange(); + break; + + case kTVModeChanged: + handleTVModeChange(NTSCFilter::Preset(myTVMode->getSelectedTag().toInt())); + break; + + case kCloneCompositeCmd: loadTVAdjustables(NTSCFilter::Preset::COMPOSITE); + break; + case kCloneSvideoCmd: loadTVAdjustables(NTSCFilter::Preset::SVIDEO); + break; + case kCloneRGBCmd: loadTVAdjustables(NTSCFilter::Preset::RGB); + break; + case kCloneBadCmd: loadTVAdjustables(NTSCFilter::Preset::BAD); + break; + case kCloneCustomCmd: loadTVAdjustables(NTSCFilter::Preset::CUSTOM); + break; + + case kScanlinesChanged: + if (myTVScanIntense->getValue() == 0) + { + myTVScanIntense->setValueLabel("Off"); + myTVScanIntense->setValueUnit(""); + } + else + myTVScanIntense->setValueUnit("%"); + break; + + case kPhosphorChanged: + handlePhosphorChange(); + break; + + case kPhosBlendChanged: + if (myTVPhosLevel->getValue() == 0) + { + myTVPhosLevel->setValueLabel("Off"); + myTVPhosLevel->setValueUnit(""); + } + else + myTVPhosLevel->setValueUnit("%"); + break; + + case kSoundEnableChanged: + updateEnabledState(); + break; + + case kModeChanged: + updatePreset(); + updateEnabledState(); + break; + + case kHeadroomChanged: + { + std::ostringstream ss; + ss << std::fixed << std::setprecision(1) << (0.5 * myHeadroomSlider->getValue()) << " frames"; + myHeadroomSlider->setValueLabel(ss.str()); + break; + } + case kBufferSizeChanged: + { + std::ostringstream ss; + ss << std::fixed << std::setprecision(1) << (0.5 * myBufferSizeSlider->getValue()) << " frames"; + myBufferSizeSlider->setValueLabel(ss.str()); + break; + } + + default: + Dialog::handleCommand(sender, cmd, data, 0); + break; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::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 VideoAudioDialog::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 + } + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::updateEnabledState() +{ + bool active = mySoundEnableCheckbox->getState(); + AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); + bool userMode = preset == AudioSettings::Preset::custom; + + myVolumeSlider->setEnabled(active); + myStereoSoundCheckbox->setEnabled(active); + myModePopup->setEnabled(active); + // enable only for Pitfall II cart + myDpcPitch->setEnabled(active && instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC"); + + myFragsizePopup->setEnabled(active && userMode); + myFreqPopup->setEnabled(active && userMode); + myResamplingPopup->setEnabled(active && userMode); + myHeadroomSlider->setEnabled(active && userMode); + myBufferSizeSlider->setEnabled(active && userMode); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::updatePreset() +{ + AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); + + // Make a copy that does not affect the actual settings... + AudioSettings audioSettings = instance().audioSettings(); + audioSettings.setPersistent(false); + // ... and set the requested preset + audioSettings.setPreset(preset); + + updateSettingsWithPreset(audioSettings); +} diff --git a/src/gui/VideoDialog.hxx b/src/gui/VideoAudioDialog.hxx similarity index 66% rename from src/gui/VideoDialog.hxx rename to src/gui/VideoAudioDialog.hxx index 429290082..f46740ae6 100644 --- a/src/gui/VideoDialog.hxx +++ b/src/gui/VideoAudioDialog.hxx @@ -15,77 +15,75 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#ifndef VIDEO_DIALOG_HXX -#define VIDEO_DIALOG_HXX +#ifndef VIDEOAUDIO_DIALOG_HXX +#define VIDEOAUDIO_DIALOG_HXX class CommandSender; class CheckboxWidget; +class ColorWidget; class DialogContainer; class PopUpWidget; +class RadioButtonGroup; class SliderWidget; class StaticTextWidget; class TabWidget; class OSystem; #include "Dialog.hxx" +#include "PaletteHandler.hxx" #include "NTSCFilter.hxx" #include "bspf.hxx" -class VideoDialog : public Dialog +class VideoAudioDialog : public Dialog { public: - VideoDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, + VideoAudioDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h); - virtual ~VideoDialog() = default; + virtual ~VideoAudioDialog() = default; private: void loadConfig() override; void saveConfig() override; void setDefaults() override; + void addDisplayTab(); + void addPaletteTab(); + void addTVEffectsTab(); + void addAudioTab(); 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(); + void updatePreset(); + void updateEnabledState(); + void updateSettingsWithPreset(AudioSettings&); private: TabWidget* myTab; // General options PopUpWidget* myRenderer{nullptr}; - SliderWidget* myTIAZoom{nullptr}; - PopUpWidget* myTIAPalette{nullptr}; - SliderWidget* myPhaseShiftNtsc{nullptr}; - SliderWidget* myPhaseShiftPal{nullptr}; CheckboxWidget* myTIAInterpolate{nullptr}; - SliderWidget* myVSizeAdjust{nullptr}; - SliderWidget* mySpeed{nullptr}; - CheckboxWidget* myFullscreen{nullptr}; //PopUpWidget* myFullScreenMode; CheckboxWidget* myUseStretch{nullptr}; SliderWidget* myTVOverscan{nullptr}; - CheckboxWidget* myUseVSync{nullptr}; - CheckboxWidget* myUIMessages{nullptr}; - CheckboxWidget* myCenter{nullptr}; - CheckboxWidget* myFastSCBios{nullptr}; - CheckboxWidget* myUseThreads{nullptr}; + SliderWidget* myTIAZoom{nullptr}; + SliderWidget* myVSizeAdjust{nullptr}; // TV effects adjustables (custom mode) PopUpWidget* myTVMode{nullptr}; SliderWidget* myTVSharp{nullptr}; - SliderWidget* myTVHue{nullptr}; SliderWidget* myTVRes{nullptr}; SliderWidget* myTVArtifacts{nullptr}; SliderWidget* myTVFringe{nullptr}; SliderWidget* myTVBleed{nullptr}; - SliderWidget* myTVBright{nullptr}; - SliderWidget* myTVContrast{nullptr}; - SliderWidget* myTVSatur{nullptr}; - SliderWidget* myTVGamma{nullptr}; // TV phosphor effect CheckboxWidget* myTVPhosphor{nullptr}; @@ -102,15 +100,44 @@ class VideoDialog : public Dialog ButtonWidget* myCloneBad{nullptr}; ButtonWidget* myCloneCustom{nullptr}; + // Palettes + PopUpWidget* myTIAPalette{nullptr}; + SliderWidget* myPhaseShiftNtsc{nullptr}; + SliderWidget* myPhaseShiftPal{nullptr}; + SliderWidget* myTVHue{nullptr}; + SliderWidget* myTVSatur{nullptr}; + SliderWidget* myTVBright{nullptr}; + SliderWidget* myTVContrast{nullptr}; + SliderWidget* myTVGamma{nullptr}; + std::array myColorLbl{nullptr}; + ColorWidget* myColor[16][8]{{nullptr}}; + + // Audio + CheckboxWidget* mySoundEnableCheckbox{nullptr}; + SliderWidget* myVolumeSlider{nullptr}; + CheckboxWidget* myStereoSoundCheckbox{nullptr}; + PopUpWidget* myModePopup{nullptr}; + PopUpWidget* myFragsizePopup{nullptr}; + PopUpWidget* myFreqPopup{nullptr}; + PopUpWidget* myResamplingPopup{nullptr}; + SliderWidget* myHeadroomSlider{nullptr}; + SliderWidget* myBufferSizeSlider{nullptr}; + SliderWidget* myDpcPitch{nullptr}; + + string myPalette; + PaletteHandler::Adjustable myPaletteAdj; + enum { - kPaletteChanged = 'VDpl', - kNtscShiftChanged = 'VDns', - kPalShiftChanged = 'VDps', - kSpeedupChanged = 'VDSp', + kZoomChanged = 'VDZo', kVSizeChanged = 'VDVs', kFullScreenChanged = 'VDFs', kOverscanChanged = 'VDOv', + kPaletteChanged = 'VDpl', + kNtscShiftChanged = 'VDns', + kPalShiftChanged = 'VDps', + kPaletteUpdated = 'VDpu', + kTVModeChanged = 'VDtv', kCloneCompositeCmd = 'CLcp', kCloneSvideoCmd = 'CLsv', @@ -119,16 +146,21 @@ class VideoDialog : public Dialog kCloneCustomCmd = 'CLcu', kPhosphorChanged = 'VDph', kPhosBlendChanged = 'VDbl', - kScanlinesChanged = 'VDsc' + kScanlinesChanged = 'VDsc', + + kSoundEnableChanged = 'ADse', + kModeChanged = 'ADmc', + kHeadroomChanged = 'ADhc', + kBufferSizeChanged = 'ADbc' }; private: // Following constructors and assignment operators not supported - VideoDialog() = delete; - VideoDialog(const VideoDialog&) = delete; - VideoDialog(VideoDialog&&) = delete; - VideoDialog& operator=(const VideoDialog&) = delete; - VideoDialog& operator=(VideoDialog&&) = delete; + VideoAudioDialog() = delete; + VideoAudioDialog(const VideoAudioDialog&) = delete; + VideoAudioDialog(VideoAudioDialog&&) = delete; + VideoAudioDialog& operator=(const VideoAudioDialog&) = delete; + VideoAudioDialog& operator=(VideoAudioDialog&&) = delete; }; #endif diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx deleted file mode 100644 index 30b7a6ccc..000000000 --- a/src/gui/VideoDialog.cxx +++ /dev/null @@ -1,772 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#include - -#include "bspf.hxx" -#include "Control.hxx" -#include "Dialog.hxx" -#include "Menu.hxx" -#include "OSystem.hxx" -#include "EditTextWidget.hxx" -#include "PopUpWidget.hxx" -#include "Console.hxx" -#include "TIA.hxx" -#include "Settings.hxx" -#include "Widget.hxx" -#include "Font.hxx" -#include "TabWidget.hxx" -#include "NTSCFilter.hxx" -#include "TIASurface.hxx" - -#include "VideoDialog.hxx" - -namespace { - // Emulation speed is a positive float that multiplies the framerate. However, the UI controls - // adjust speed in terms of a speedup factor (1/10, 1/9 .. 1/2, 1, 2, 3, .., 10). The following - // mapping and formatting functions implement this conversion. The speedup factor is represented - // by an integer value between -900 and 900 (0 means no speedup). - - constexpr int MAX_SPEED = 900; - constexpr int MIN_SPEED = -900; - constexpr int SPEED_STEP = 10; - - int mapSpeed(float speed) - { - speed = std::abs(speed); - - return BSPF::clamp( - static_cast(round(100 * (speed >= 1 ? speed - 1 : -1 / speed + 1))), - MIN_SPEED, MAX_SPEED - ); - } - - float unmapSpeed(int speed) - { - float f_speed = static_cast(speed) / 100; - - return speed < 0 ? -1 / (f_speed - 1) : 1 + f_speed; - } - - string formatSpeed(int speed) { - stringstream ss; - - ss - << std::setw(3) << std::fixed << std::setprecision(0) - << (unmapSpeed(speed) * 100); - - return ss.str(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, - const GUI::Font& font, int max_w, int max_h) - : Dialog(osystem, parent, font, "Video settings") -{ - const int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(), - buttonHeight = font.getLineHeight() * 1.25; - const int VGAP = fontHeight / 4; - const int VBORDER = fontHeight / 2; - const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; - - int xpos, ypos, tabID; - int lwidth = font.getStringWidth("V-Size adjust "), - pwidth = font.getStringWidth("XXXXxXXXX"); - - WidgetArray wid; - VariantList items; - - // Set real dimensions - setSize(57 * fontWidth + HBORDER * 2 + PopUpWidget::dropDownWidth(font) * 2, - _th + VGAP * 3 + lineHeight + 11 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3, - max_w, max_h); - - // The tab widget - xpos = 2; ypos = VGAP; - myTab = new TabWidget(this, font, xpos, ypos + _th, - _w - 2*xpos, - _h - _th - VGAP - buttonHeight - VBORDER * 2); - addTabWidget(myTab); - - xpos = HBORDER; ypos = VBORDER; - ////////////////////////////////////////////////////////// - // 1) General options - tabID = myTab->addTab(" General "); - - // Video renderer - myRenderer = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - instance().frameBuffer().supportedRenderers(), - "Renderer ", lwidth); - wid.push_back(myRenderer); - ypos += lineHeight + VGAP; - - // TIA Palette - items.clear(); - VarList::push_back(items, "Standard", "standard"); - VarList::push_back(items, "z26", "z26"); - if (instance().checkUserPalette()) - VarList::push_back(items, "User", "user"); - VarList::push_back(items, "Custom", "custom"); - myTIAPalette = new PopUpWidget(myTab, font, xpos, ypos, pwidth, - lineHeight, items, "Palette ", lwidth, kPaletteChanged); - wid.push_back(myTIAPalette); - ypos += lineHeight + VGAP; - - int swidth = myTIAPalette->getWidth() - lwidth; - int plWidth = font.getStringWidth("NTSC phase "); - int pswidth = swidth - INDENT + lwidth - plWidth; - - 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->setTickmarkIntervals(4); - wid.push_back(myPhaseShiftNtsc); - ypos += lineHeight + VGAP; - - 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->setTickmarkIntervals(4); - wid.push_back(myPhaseShiftPal); - ypos += lineHeight + VGAP * 4; - - // TIA interpolation - myTIAInterpolate = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Interpolation "); - wid.push_back(myTIAInterpolate); ypos += lineHeight + VGAP; - - - // TIA zoom levels (will be dynamically filled later) - myTIAZoom = new SliderWidget(myTab, font, xpos, ypos - 1, swidth, lineHeight, - "Zoom ", lwidth, 0, fontWidth * 4, "%"); - myTIAZoom->setMinValue(200); myTIAZoom->setStepValue(FrameBuffer::ZOOM_STEPS * 100); - wid.push_back(myTIAZoom); - ypos += lineHeight + VGAP; - - // Aspect ratio (NTSC mode) - myVSizeAdjust = - new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, - "V-Size adjust", lwidth, kVSizeChanged, fontWidth * 7, "%", 0, true); - myVSizeAdjust->setMinValue(-5); myVSizeAdjust->setMaxValue(5); - myVSizeAdjust->setTickmarkIntervals(2); - wid.push_back(myVSizeAdjust); - ypos += lineHeight + VGAP; - - // Speed - mySpeed = - new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, - "Emul. speed ", lwidth, kSpeedupChanged, fontWidth * 5, "%"); - mySpeed->setMinValue(MIN_SPEED); mySpeed->setMaxValue(MAX_SPEED); - mySpeed->setStepValue(SPEED_STEP); - mySpeed->setTickmarkIntervals(2); - wid.push_back(mySpeed); - ypos += lineHeight + VGAP; - - // Use sync to vblank - myUseVSync = new CheckboxWidget(myTab, font, xpos, ypos + 1, "VSync"); - wid.push_back(myUseVSync); - - // Move over to the next column - xpos = myVSizeAdjust->getRight() + fontWidth * 3; - ypos = VBORDER; - - // Fullscreen - myFullscreen = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fullscreen", kFullScreenChanged); - wid.push_back(myFullscreen); - ypos += lineHeight + VGAP; - - /*pwidth = font.getStringWidth("0: 3840x2860@120Hz"); - myFullScreenMode = new PopUpWidget(myTab, font, xpos + INDENT + 2, ypos, pwidth, lineHeight, - instance().frameBuffer().supportedScreenModes(), "Mode "); - wid.push_back(myFullScreenMode); - ypos += lineHeight + VGAP;*/ - - // FS stretch - myUseStretch = new CheckboxWidget(myTab, font, xpos + INDENT, ypos + 1, "Stretch"); - wid.push_back(myUseStretch); - ypos += lineHeight + VGAP; - - // FS overscan - myTVOverscan = new SliderWidget(myTab, font, xpos + INDENT, ypos - 1, swidth, lineHeight, - "Overscan", font.getStringWidth("Overscan "), kOverscanChanged, fontWidth * 3, "%"); - myTVOverscan->setMinValue(0); myTVOverscan->setMaxValue(10); - myTVOverscan->setTickmarkIntervals(2); - wid.push_back(myTVOverscan); - ypos += (lineHeight + VGAP) * 2; - - // Skip progress load bars for SuperCharger ROMs - // Doesn't really belong here, but I couldn't find a better place for it - myFastSCBios = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fast SuperCharger load"); - wid.push_back(myFastSCBios); - ypos += lineHeight + VGAP; - - // Show UI messages onscreen - myUIMessages = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Show UI messages"); - wid.push_back(myUIMessages); - ypos += lineHeight + VGAP; - - // Center window (in windowed mode) - myCenter = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Center window"); - wid.push_back(myCenter); - ypos += (lineHeight + VGAP) * 2; - - // Use multi-threading - myUseThreads = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Multi-threading"); - wid.push_back(myUseThreads); - - // Add items for tab 0 - addToFocusList(wid, myTab, tabID); - - ////////////////////////////////////////////////////////// - // 2) TV effects options - wid.clear(); - tabID = myTab->addTab(" TV Effects "); - xpos = HBORDER; - ypos = VBORDER; - swidth = fontWidth * 8 - fontWidth / 2; - - // TV Mode - items.clear(); - VarList::push_back(items, "Disabled", static_cast(NTSCFilter::Preset::OFF)); - VarList::push_back(items, "RGB", static_cast(NTSCFilter::Preset::RGB)); - VarList::push_back(items, "S-Video", static_cast(NTSCFilter::Preset::SVIDEO)); - VarList::push_back(items, "Composite", static_cast(NTSCFilter::Preset::COMPOSITE)); - VarList::push_back(items, "Bad adjust", static_cast(NTSCFilter::Preset::BAD)); - VarList::push_back(items, "Custom", static_cast(NTSCFilter::Preset::CUSTOM)); - lwidth = font.getStringWidth("TV Mode "); - pwidth = font.getStringWidth("Bad adjust"); - myTVMode = - new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - items, "TV mode ", lwidth, kTVModeChanged); - wid.push_back(myTVMode); - ypos += lineHeight + VGAP; - - // Custom adjustables (using macro voodoo) - xpos += INDENT - 2; ypos += 0; - lwidth = font.getStringWidth("Saturation "); - -#define CREATE_CUSTOM_SLIDERS(obj, desc, cmd) \ - myTV ## obj = \ - new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, \ - desc, lwidth, cmd, fontWidth*4, "%"); \ - myTV ## obj->setMinValue(0); myTV ## obj->setMaxValue(100); \ - myTV ## obj->setTickmarkIntervals(2); \ - wid.push_back(myTV ## obj); \ - ypos += lineHeight + VGAP; - - CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", 0) - CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", 0) - CREATE_CUSTOM_SLIDERS(Hue, "Hue ", 0) - CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", 0) - CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", 0) - CREATE_CUSTOM_SLIDERS(Sharp, "Sharpness ", 0) - CREATE_CUSTOM_SLIDERS(Res, "Resolution ", 0) - CREATE_CUSTOM_SLIDERS(Artifacts, "Artifacts ", 0) - CREATE_CUSTOM_SLIDERS(Fringe, "Fringing ", 0) - CREATE_CUSTOM_SLIDERS(Bleed, "Bleeding ", 0) - - xpos += myTVContrast->getWidth() + fontWidth * 6; - ypos = VBORDER; - - lwidth = font.getStringWidth("Intensity "); - - // TV Phosphor effect - myTVPhosphor = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Phosphor for all ROMs", kPhosphorChanged); - wid.push_back(myTVPhosphor); - ypos += lineHeight + VGAP / 2; - - // TV Phosphor blend level - xpos += INDENT; - swidth = font.getMaxCharWidth() * 10; - CREATE_CUSTOM_SLIDERS(PhosLevel, "Blend ", kPhosBlendChanged) - ypos += VGAP * 2; - - // Scanline intensity and interpolation - xpos -= INDENT; - myTVScanLabel = new StaticTextWidget(myTab, font, xpos, ypos, "Scanlines:"); - ypos += lineHeight + VGAP / 2; - - xpos += INDENT; - CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity ", kScanlinesChanged) - ypos += VGAP * 3; - - // Adjustable presets - xpos -= INDENT; - int cloneWidth = font.getStringWidth("Clone Bad Adjust") + 20; -#define CREATE_CLONE_BUTTON(obj, desc) \ - myClone ## obj = \ - new ButtonWidget(myTab, font, xpos, ypos, cloneWidth, buttonHeight,\ - desc, kClone ## obj ##Cmd); \ - wid.push_back(myClone ## obj); \ - ypos += buttonHeight + VGAP; - - ypos += VGAP; - CREATE_CLONE_BUTTON(RGB, "Clone RGB") - CREATE_CLONE_BUTTON(Svideo, "Clone S-Video") - CREATE_CLONE_BUTTON(Composite, "Clone Composite") - CREATE_CLONE_BUTTON(Bad, "Clone Bad adjust") - CREATE_CLONE_BUTTON(Custom, "Revert") - - // Add items for tab 2 - addToFocusList(wid, myTab, tabID); - - // Activate the first tab - myTab->setActiveTab(0); - - // Add Defaults, OK and Cancel buttons - wid.clear(); - addDefaultsOKCancelBGroup(wid, font); - addBGroupToFocusList(wid); - - // Disable certain functions when we know they aren't present -#ifndef WINDOWED_SUPPORT - myFullscreen->clearFlags(Widget::FLAG_ENABLED); - myCenter->clearFlags(Widget::FLAG_ENABLED); -#endif -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::loadConfig() -{ - // Renderer settings - myRenderer->setSelected(instance().settings().getString("video"), "default"); - - // TIA zoom levels - // These are dynamically loaded, since they depend on the size of - // the desktop and which renderer we're using - float minZoom = instance().frameBuffer().supportedTIAMinZoom(); // or 2 if we allow lower values - float maxZoom = instance().frameBuffer().supportedTIAMaxZoom(); - - myTIAZoom->setMinValue(minZoom * 100); - myTIAZoom->setMaxValue(maxZoom * 100); - myTIAZoom->setTickmarkIntervals((maxZoom - minZoom) * 2); // every ~50% - myTIAZoom->setValue(instance().settings().getFloat("tia.zoom") * 100); - - // TIA Palette - myTIAPalette->setSelected( - instance().settings().getString("palette"), "standard"); - - // Custom Palette - myPhaseShiftNtsc->setValue(instance().settings().getFloat("phase_ntsc") * 10); - myPhaseShiftPal->setValue(instance().settings().getFloat("phase_pal") * 10); - handlePaletteChange(); - - // TIA interpolation - myTIAInterpolate->setState(instance().settings().getBool("tia.inter")); - - // Aspect ratio setting (NTSC and PAL) - myVSizeAdjust->setValue(instance().settings().getInt("tia.vsizeadjust")); - - // Emulation speed - int speed = mapSpeed(instance().settings().getFloat("speed")); - mySpeed->setValue(speed); - mySpeed->setValueLabel(formatSpeed(speed)); - - // Fullscreen - myFullscreen->setState(instance().settings().getBool("fullscreen")); - /*string mode = instance().settings().getString("fullscreenmode"); - myFullScreenMode->setSelected(mode);*/ - // Fullscreen stretch setting - myUseStretch->setState(instance().settings().getBool("tia.fs_stretch")); - // Fullscreen overscan setting - myTVOverscan->setValue(instance().settings().getInt("tia.fs_overscan")); - handleFullScreenChange(); - - // Use sync to vertical blank - myUseVSync->setState(instance().settings().getBool("vsync")); - - // Show UI messages - myUIMessages->setState(instance().settings().getBool("uimessages")); - - // Center window - myCenter->setState(instance().settings().getBool("center")); - - // Fast loading of Supercharger BIOS - myFastSCBios->setState(instance().settings().getBool("fastscbios")); - - // Multi-threaded rendering - myUseThreads->setState(instance().settings().getBool("threads")); - - // TV Mode - myTVMode->setSelected( - instance().settings().getString("tv.filter"), "0"); - int preset = instance().settings().getInt("tv.filter"); - handleTVModeChange(NTSCFilter::Preset(preset)); - - // TV Custom adjustables - loadTVAdjustables(NTSCFilter::Preset::CUSTOM); - - // TV phosphor mode - myTVPhosphor->setState(instance().settings().getString("tv.phosphor") == "always"); - - // TV phosphor blend - myTVPhosLevel->setValue(instance().settings().getInt("tv.phosblend")); - handlePhosphorChange(); - - // TV scanline intensity and interpolation - myTVScanIntense->setValue(instance().settings().getInt("tv.scanlines")); - - myTab->loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::saveConfig() -{ - // Renderer setting - 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("phase_ntsc", myPhaseShiftNtsc->getValue() / 10.0); - instance().settings().setValue("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); - - // Speed - int speedup = mySpeed->getValue(); - instance().settings().setValue("speed", unmapSpeed(speedup)); - if (instance().hasConsole()) instance().console().initializeAudio(); - - // Fullscreen - instance().settings().setValue("fullscreen", myFullscreen->getState()); - // Fullscreen stretch setting - instance().settings().setValue("tia.fs_stretch", myUseStretch->getState()); - // Fullscreen overscan - instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel()); - - // Use sync to vertical blank - instance().settings().setValue("vsync", myUseVSync->getState()); - - // Show UI messages - instance().settings().setValue("uimessages", myUIMessages->getState()); - - // Center window - instance().settings().setValue("center", myCenter->getState()); - - // Fast loading of Supercharger BIOS - instance().settings().setValue("fastscbios", myFastSCBios->getState()); - - // Multi-threaded rendering - instance().settings().setValue("threads", myUseThreads->getState()); - if (instance().hasConsole()) - instance().frameBuffer().tiaSurface().ntsc().enableThreading(myUseThreads->getState()); - - // TV Mode - instance().settings().setValue("tv.filter", - myTVMode->getSelectedTag().toString()); - - // TV Custom adjustables - NTSCFilter::Adjustable adj; - adj.hue = myTVHue->getValue(); - adj.saturation = myTVSatur->getValue(); - adj.contrast = myTVContrast->getValue(); - adj.brightness = myTVBright->getValue(); - adj.sharpness = myTVSharp->getValue(); - adj.gamma = myTVGamma->getValue(); - adj.resolution = myTVRes->getValue(); - adj.artifacts = myTVArtifacts->getValue(); - adj.fringing = myTVFringe->getValue(); - adj.bleed = myTVBleed->getValue(); - instance().frameBuffer().tiaSurface().ntsc().setCustomAdjustables(adj); - - // TV phosphor mode - instance().settings().setValue("tv.phosphor", - myTVPhosphor->getState() ? "always" : "byrom"); - // TV phosphor blend - instance().settings().setValue("tv.phosblend", myTVPhosLevel->getValueLabel() == "Off" - ? "0" : myTVPhosLevel->getValueLabel()); - - // TV scanline intensity - instance().settings().setValue("tv.scanlines", myTVScanIntense->getValueLabel()); - - if(instance().hasConsole()) - { - instance().console().setTIAProperties(); - - if(instance().settings().getString("palette") == "custom") - { - instance().console().generateCustomPalette(0); - instance().console().generateCustomPalette(1); - } - - if(vsizeChanged) - { - instance().console().tia().clearFrameBuffer(); - instance().console().initializeVideo(); - } - } - - // Finally, issue a complete framebuffer re-initialization... - instance().createFrameBuffer(); - - // ... and apply potential setting changes to the TIA surface - instance().frameBuffer().tiaSurface().updateSurfaceSettings(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::setDefaults() -{ - switch(myTab->getActiveTab()) - { - case 0: // General - { - myRenderer->setSelectedIndex(0); - myTIAZoom->setValue(300); - myTIAPalette->setSelected("standard", ""); - myPhaseShiftNtsc->setValue(262); - myPhaseShiftPal->setValue(313); - myTIAInterpolate->setState(false); - myVSizeAdjust->setValue(0); - mySpeed->setValue(0); - - myFullscreen->setState(false); - //myFullScreenMode->setSelectedIndex(0); - myUseStretch->setState(false); - myUseVSync->setState(true); - myUIMessages->setState(true); - myCenter->setState(false); - myFastSCBios->setState(true); - myUseThreads->setState(false); - - handlePaletteChange(); - break; - } - - case 1: // TV effects - { - myTVMode->setSelected("0", "0"); - - // TV phosphor mode - myTVPhosphor->setState(false); - - // TV phosphor blend - myTVPhosLevel->setValue(50); - - // TV scanline intensity and interpolation - myTVScanIntense->setValue(25); - - // Make sure that mutually-exclusive items are not enabled at the same time - handleTVModeChange(NTSCFilter::Preset::OFF); - handlePhosphorChange(); - loadTVAdjustables(NTSCFilter::Preset::CUSTOM); - break; - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleTVModeChange(NTSCFilter::Preset preset) -{ - bool enable = preset == NTSCFilter::Preset::CUSTOM; - - myTVSharp->setEnabled(enable); - myTVHue->setEnabled(enable); - myTVRes->setEnabled(enable); - myTVArtifacts->setEnabled(enable); - myTVFringe->setEnabled(enable); - myTVBleed->setEnabled(enable); - myTVBright->setEnabled(enable); - myTVContrast->setEnabled(enable); - myTVSatur->setEnabled(enable); - myTVGamma->setEnabled(enable); - myCloneComposite->setEnabled(enable); - myCloneSvideo->setEnabled(enable); - myCloneRGB->setEnabled(enable); - myCloneBad->setEnabled(enable); - myCloneCustom->setEnabled(enable); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::loadTVAdjustables(NTSCFilter::Preset preset) -{ - NTSCFilter::Adjustable adj; - instance().frameBuffer().tiaSurface().ntsc().getAdjustables( - adj, NTSCFilter::Preset(preset)); - myTVSharp->setValue(adj.sharpness); - myTVHue->setValue(adj.hue); - myTVRes->setValue(adj.resolution); - myTVArtifacts->setValue(adj.artifacts); - myTVFringe->setValue(adj.fringing); - myTVBleed->setValue(adj.bleed); - myTVBright->setValue(adj.brightness); - myTVContrast->setValue(adj.contrast); - myTVSatur->setValue(adj.saturation); - myTVGamma->setValue(adj.gamma); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handlePaletteChange() -{ - bool enable = myTIAPalette->getSelectedTag().toString() == "custom"; - - myPhaseShiftNtsc->setEnabled(enable); - myPhaseShiftPal->setEnabled(enable); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleFullScreenChange() -{ - bool enable = myFullscreen->getState(); - myUseStretch->setEnabled(enable); - myTVOverscan->setEnabled(enable); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleOverscanChange() -{ - if (myTVOverscan->getValue() == 0) - { - myTVOverscan->setValueLabel("Off"); - myTVOverscan->setValueUnit(""); - } - else - myTVOverscan->setValueUnit("%"); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handlePhosphorChange() -{ - myTVPhosLevel->setEnabled(myTVPhosphor->getState()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleCommand(CommandSender* sender, int cmd, - int data, int id) -{ - switch (cmd) - { - case GuiObject::kOKCmd: - saveConfig(); - close(); - break; - - case GuiObject::kDefaultsCmd: - setDefaults(); - break; - - case kPaletteChanged: - handlePaletteChange(); - break; - - case kNtscShiftChanged: - { - std::ostringstream ss; - - ss << std::setw(4) << std::fixed << std::setprecision(1) - << (0.1 * abs(myPhaseShiftNtsc->getValue())) << DEGREE; - myPhaseShiftNtsc->setValueLabel(ss.str()); - break; - } - case kPalShiftChanged: - { - std::ostringstream ss; - - ss << std::setw(4) << std::fixed << std::setprecision(1) - << (0.1 * abs(myPhaseShiftPal->getValue())) << DEGREE; - myPhaseShiftPal->setValueLabel(ss.str()); - break; - } - case kVSizeChanged: - { - int adjust = myVSizeAdjust->getValue(); - - if (!adjust) - { - myVSizeAdjust->setValueLabel("Default"); - myVSizeAdjust->setValueUnit(""); - } - else - myVSizeAdjust->setValueUnit("%"); - break; - } - - case kSpeedupChanged: - mySpeed->setValueLabel(formatSpeed(mySpeed->getValue())); - break; - - case kFullScreenChanged: - handleFullScreenChange(); - break; - - case kOverscanChanged: - handleOverscanChange(); - break; - - case kTVModeChanged: - handleTVModeChange(NTSCFilter::Preset(myTVMode->getSelectedTag().toInt())); - break; - - case kCloneCompositeCmd: loadTVAdjustables(NTSCFilter::Preset::COMPOSITE); - break; - case kCloneSvideoCmd: loadTVAdjustables(NTSCFilter::Preset::SVIDEO); - break; - case kCloneRGBCmd: loadTVAdjustables(NTSCFilter::Preset::RGB); - break; - case kCloneBadCmd: loadTVAdjustables(NTSCFilter::Preset::BAD); - break; - case kCloneCustomCmd: loadTVAdjustables(NTSCFilter::Preset::CUSTOM); - break; - - case kScanlinesChanged: - if (myTVScanIntense->getValue() == 0) - { - myTVScanIntense->setValueLabel("Off"); - myTVScanIntense->setValueUnit(""); - } - else - myTVScanIntense->setValueUnit("%"); - break; - - case kPhosphorChanged: - handlePhosphorChange(); - break; - - case kPhosBlendChanged: - if (myTVPhosLevel->getValue() == 0) - { - myTVPhosLevel->setValueLabel("Off"); - myTVPhosLevel->setValueUnit(""); - } - else - myTVPhosLevel->setValueUnit("%"); - break; - - default: - Dialog::handleCommand(sender, cmd, data, 0); - break; - } -} diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index eb31f7cd4..c2a0b6b65 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -31,6 +31,7 @@ namespace GUI { #include "bspf.hxx" #include "Event.hxx" +#include "StellaKeys.hxx" #include "GuiObject.hxx" #include "Font.hxx" diff --git a/src/gui/module.mk b/src/gui/module.mk index f550e167d..1447b8195 100644 --- a/src/gui/module.mk +++ b/src/gui/module.mk @@ -2,7 +2,6 @@ MODULE := src/gui MODULE_OBJS := \ src/gui/AboutDialog.o \ - src/gui/AudioDialog.o \ src/gui/BrowserDialog.o \ src/gui/CheckListWidget.o \ src/gui/ColorWidget.o \ @@ -15,6 +14,7 @@ MODULE_OBJS := \ src/gui/Dialog.o \ src/gui/EditableWidget.o \ src/gui/EditTextWidget.o \ + src/gui/EmulationDialog.o \ src/gui/EventMappingWidget.o \ src/gui/FileListWidget.o \ src/gui/Font.o \ @@ -49,7 +49,7 @@ MODULE_OBJS := \ src/gui/TimeMachineDialog.o \ src/gui/TimeMachine.o \ src/gui/UIDialog.o \ - src/gui/VideoDialog.o \ + src/gui/VideoAudioDialog.o \ src/gui/Widget.o MODULE_DIRS += \ diff --git a/src/libpng/pngconf.h b/src/libpng/pngconf.h index 927a769db..b5f468ae5 100644 --- a/src/libpng/pngconf.h +++ b/src/libpng/pngconf.h @@ -230,7 +230,7 @@ * the type. */ # ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# define PNG_EXPORT_TYPE(name) name PNG_IMPEXP # endif # define PNG_DLL_EXPORT __export # else /* newer compiler */ @@ -450,7 +450,7 @@ # define PNG_FP_EXPORT(ordinal, type, name, args)\ PNG_EXPORT(ordinal, type, name, args); # else /* No floating point APIs */ -# define PNG_FP_EXPORT(ordinal, type, name, args) +# define PNG_FP_EXPORT(ordinal, name, name, args) # endif #endif #ifndef PNG_FIXED_EXPORT /* A fixed point API. */ @@ -458,7 +458,7 @@ # define PNG_FIXED_EXPORT(ordinal, type, name, args)\ PNG_EXPORT(ordinal, type, name, args); # else /* No fixed point APIs */ -# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# define PNG_FIXED_EXPORT(ordinal, name, name, args) # endif #endif diff --git a/src/libretro/Makefile.common b/src/libretro/Makefile.common index 1893fa57b..5fafdd855 100644 --- a/src/libretro/Makefile.common +++ b/src/libretro/Makefile.common @@ -23,6 +23,7 @@ SOURCES_CXX := \ $(CORE_DIR)/common/KeyMap.cxx \ $(CORE_DIR)/common/Logger.cxx \ $(CORE_DIR)/common/MouseControl.cxx \ + $(CORE_DIR)/common/PaletteHandler.cxx \ $(CORE_DIR)/common/PhosphorHandler.cxx \ $(CORE_DIR)/common/PhysicalJoystick.cxx \ $(CORE_DIR)/common/PJoystickHandler.cxx \ diff --git a/src/libretro/StellaLIBRETRO.cxx b/src/libretro/StellaLIBRETRO.cxx index e3cb5073a..065917c15 100644 --- a/src/libretro/StellaLIBRETRO.cxx +++ b/src/libretro/StellaLIBRETRO.cxx @@ -40,7 +40,7 @@ StellaLIBRETRO::StellaLIBRETRO() video_aspect_ntsc = 0; video_aspect_pal = 0; - video_palette = "standard"; + video_palette = PaletteHandler::SETTING_STANDARD; video_filter = NTSCFilter::Preset::OFF; video_ready = false; @@ -374,19 +374,12 @@ void StellaLIBRETRO::setVideoFilter(NTSCFilter::Preset mode) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void StellaLIBRETRO::setVideoPalette(uInt32 mode) +void StellaLIBRETRO::setVideoPalette(const string& mode) { - switch (mode) - { - case 0: video_palette = "standard"; break; - case 1: video_palette = "z26"; break; - case 2: video_palette = "user"; break; - } - if (system_ready) { myOSystem->settings().setValue("palette", video_palette); - myOSystem->console().setPalette(video_palette); + myOSystem->frameBuffer().tiaSurface().paletteHandler().setPalette(video_palette); } } diff --git a/src/libretro/StellaLIBRETRO.hxx b/src/libretro/StellaLIBRETRO.hxx index f48a13708..3078e8eb1 100644 --- a/src/libretro/StellaLIBRETRO.hxx +++ b/src/libretro/StellaLIBRETRO.hxx @@ -104,7 +104,7 @@ class StellaLIBRETRO void setVideoAspectPAL(uInt32 value) { video_aspect_pal = value; }; void setVideoFilter(NTSCFilter::Preset mode); - void setVideoPalette(uInt32 mode); + void setVideoPalette(const string& mode); void setVideoPhosphor(uInt32 mode, uInt32 blend); void setAudioStereo(int mode); diff --git a/src/libretro/libretro.cxx b/src/libretro/libretro.cxx index 6babbf07f..8caae3765 100644 --- a/src/libretro/libretro.cxx +++ b/src/libretro/libretro.cxx @@ -15,6 +15,7 @@ #include "StellaLIBRETRO.hxx" #include "Event.hxx" #include "NTSCFilter.hxx" +#include "PaletteHandler.hxx" #include "Version.hxx" @@ -30,11 +31,12 @@ static retro_audio_sample_batch_t audio_batch_cb; // libretro UI settings static int setting_ntsc, setting_pal; -static int setting_stereo, setting_palette; +static int setting_stereo; static int setting_phosphor, setting_console, setting_phosphor_blend; static int stella_paddle_joypad_sensitivity; static int setting_crop_hoverscan, crop_left; static NTSCFilter::Preset setting_filter; +static const char* setting_palette; static bool system_reset; @@ -275,17 +277,11 @@ static void update_variables(bool init = false) RETRO_GET("stella_palette") { - int value = 0; - - if(!strcmp(var.value, "standard")) value = 0; - else if(!strcmp(var.value, "z26")) value = 1; - else if(!strcmp(var.value, "user")) value = 2; - - if(setting_palette != value) + if(setting_palette != var.value) { - stella.setVideoPalette(value); + stella.setVideoPalette(var.value); - setting_palette = value; + setting_palette = var.value; } } @@ -494,7 +490,7 @@ void retro_set_environment(retro_environment_t cb) static struct retro_variable variables[] = { // Adding more variables and rearranging them is safe. { "stella_console", "Console display; auto|ntsc|pal|secam|ntsc50|pal60|secam60" }, - { "stella_palette", "Palette colors; standard|z26|user" }, + { "stella_palette", "Palette colors; standard|z26|user|custom" }, { "stella_filter", "TV effects; disabled|composite|s-video|rgb|badly adjusted" }, { "stella_ntsc_aspect", "NTSC aspect %; par|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99" }, { "stella_pal_aspect", "PAL aspect %; par|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99" }, diff --git a/src/macos/stella.xcodeproj/project.pbxproj b/src/macos/stella.xcodeproj/project.pbxproj index 33eccde69..d59aac510 100644 --- a/src/macos/stella.xcodeproj/project.pbxproj +++ b/src/macos/stella.xcodeproj/project.pbxproj @@ -44,7 +44,6 @@ 2D9173FA09BA90380026E9FF /* FrameBuffer.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2D733D71062895B2006265D9 /* FrameBuffer.hxx */; }; 2D9173FB09BA90380026E9FF /* Settings.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2D733D77062895F1006265D9 /* Settings.hxx */; }; 2D91740009BA90380026E9FF /* AboutDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAA4084578BF00812C11 /* AboutDialog.hxx */; }; - 2D91740109BA90380026E9FF /* AudioDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAA7084578BF00812C11 /* AudioDialog.hxx */; }; 2D91740209BA90380026E9FF /* BrowserDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAA9084578BF00812C11 /* BrowserDialog.hxx */; }; 2D91740309BA90380026E9FF /* Command.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAAA084578BF00812C11 /* Command.hxx */; }; 2D91740409BA90380026E9FF /* Dialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAAC084578BF00812C11 /* Dialog.hxx */; }; @@ -61,7 +60,6 @@ 2D91741209BA90380026E9FF /* ProgressDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAC9084578BF00812C11 /* ProgressDialog.hxx */; }; 2D91741309BA90380026E9FF /* ScrollBarWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEACB084578BF00812C11 /* ScrollBarWidget.hxx */; }; 2D91741609BA90380026E9FF /* TabWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAD1084578BF00812C11 /* TabWidget.hxx */; }; - 2D91741709BA90380026E9FF /* VideoDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAD3084578BF00812C11 /* VideoDialog.hxx */; }; 2D91741809BA90380026E9FF /* Widget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAD5084578BF00812C11 /* Widget.hxx */; }; 2D91741909BA90380026E9FF /* CartUA.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEB7108457B7D00812C11 /* CartUA.hxx */; }; 2D91741A09BA90380026E9FF /* FSNode.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEB7308457B7D00812C11 /* FSNode.hxx */; }; @@ -142,7 +140,6 @@ 2D9174A309BA90380026E9FF /* Settings.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2D944848062904E800DD9879 /* Settings.cxx */; }; 2D9174A809BA90380026E9FF /* FSNodePOSIX.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEA0C0845708800812C11 /* FSNodePOSIX.cxx */; }; 2D9174AA09BA90380026E9FF /* AboutDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAA3084578BF00812C11 /* AboutDialog.cxx */; }; - 2D9174AB09BA90380026E9FF /* AudioDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAA6084578BF00812C11 /* AudioDialog.cxx */; }; 2D9174AC09BA90380026E9FF /* BrowserDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAA8084578BF00812C11 /* BrowserDialog.cxx */; }; 2D9174AD09BA90380026E9FF /* Dialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAAB084578BF00812C11 /* Dialog.cxx */; }; 2D9174AE09BA90380026E9FF /* DialogContainer.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAAD084578BF00812C11 /* DialogContainer.cxx */; }; @@ -157,7 +154,6 @@ 2D9174B909BA90380026E9FF /* ProgressDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAC8084578BF00812C11 /* ProgressDialog.cxx */; }; 2D9174BA09BA90380026E9FF /* ScrollBarWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEACA084578BF00812C11 /* ScrollBarWidget.cxx */; }; 2D9174BB09BA90380026E9FF /* TabWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAD0084578BF00812C11 /* TabWidget.cxx */; }; - 2D9174BC09BA90380026E9FF /* VideoDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAD2084578BF00812C11 /* VideoDialog.cxx */; }; 2D9174BD09BA90380026E9FF /* Widget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAD4084578BF00812C11 /* Widget.cxx */; }; 2D9174BE09BA90380026E9FF /* CartUA.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEB7008457B7D00812C11 /* CartUA.cxx */; }; 2D9174BF09BA90380026E9FF /* FSNode.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEB7208457B7D00812C11 /* FSNode.cxx */; }; @@ -233,8 +229,6 @@ DC2410E32274BDA8007A4CBF /* MinUICommandDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2410E12274BDA7007A4CBF /* MinUICommandDialog.hxx */; }; DC2410E42274BDA8007A4CBF /* MinUICommandDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2410E22274BDA8007A4CBF /* MinUICommandDialog.cxx */; }; DC2874071F8F2278004BF21A /* TrapArray.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2874061F8F2278004BF21A /* TrapArray.hxx */; }; - DC2AADAE194F389C0026C7A4 /* CartDASH.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */; }; - DC2AADAF194F389C0026C7A4 /* CartDASH.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */; }; DC2AADB0194F389C0026C7A4 /* TIASurface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADAC194F389C0026C7A4 /* TIASurface.cxx */; }; DC2AADB1194F389C0026C7A4 /* TIASurface.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2AADAD194F389C0026C7A4 /* TIASurface.hxx */; }; DC2AADB4194F390F0026C7A4 /* CartRamWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADB2194F390F0026C7A4 /* CartRamWidget.cxx */; }; @@ -250,6 +244,18 @@ DC368F5918A2FB710084199C /* SoundSDL2.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC368F5318A2FB710084199C /* SoundSDL2.hxx */; }; DC36D2C814CAFAB0007DC821 /* CartFA2.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC36D2C614CAFAB0007DC821 /* CartFA2.cxx */; }; DC36D2C914CAFAB0007DC821 /* CartFA2.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC36D2C714CAFAB0007DC821 /* CartFA2.hxx */; }; + DC3C9BC52469C8F700CF2D47 /* PaletteHandler.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BC32469C8F700CF2D47 /* PaletteHandler.cxx */; }; + DC3C9BC62469C8F700CF2D47 /* PaletteHandler.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BC42469C8F700CF2D47 /* PaletteHandler.hxx */; }; + DC3C9BCB2469C93D00CF2D47 /* VideoAudioDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BC72469C93D00CF2D47 /* VideoAudioDialog.cxx */; }; + DC3C9BCC2469C93D00CF2D47 /* EmulationDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BC82469C93D00CF2D47 /* EmulationDialog.cxx */; }; + DC3C9BCD2469C93D00CF2D47 /* VideoAudioDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BC92469C93D00CF2D47 /* VideoAudioDialog.hxx */; }; + DC3C9BCE2469C93D00CF2D47 /* EmulationDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BCA2469C93D00CF2D47 /* EmulationDialog.hxx */; }; + DC3C9BD32469C9A200CF2D47 /* CartEnhanced.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BCF2469C9A200CF2D47 /* CartEnhanced.cxx */; }; + DC3C9BD42469C9A200CF2D47 /* Cart3EX.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BD02469C9A200CF2D47 /* Cart3EX.hxx */; }; + DC3C9BD52469C9A200CF2D47 /* CartEnhanced.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BD12469C9A200CF2D47 /* CartEnhanced.hxx */; }; + DC3C9BD62469C9A200CF2D47 /* Cart3EX.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BD22469C9A200CF2D47 /* Cart3EX.cxx */; }; + DC3C9BD92469C9C700CF2D47 /* CartEnhancedWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BD72469C9C700CF2D47 /* CartEnhancedWidget.cxx */; }; + DC3C9BDA2469C9C700CF2D47 /* CartEnhancedWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BD82469C9C700CF2D47 /* CartEnhancedWidget.hxx */; }; DC3DAFAC1F2E233B00A64410 /* PointingDevice.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3DAFAB1F2E233B00A64410 /* PointingDevice.hxx */; }; DC3EE8561E2C0E6D00905161 /* adler32.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3EE83C1E2C0E6D00905161 /* adler32.c */; settings = {COMPILER_FLAGS = "-w"; }; }; DC3EE8571E2C0E6D00905161 /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3EE83D1E2C0E6D00905161 /* compress.c */; settings = {COMPILER_FLAGS = "-w"; }; }; @@ -393,8 +399,6 @@ DC73BD891915E5E3003FAFAD /* FBSurface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC73BD871915E5E3003FAFAD /* FBSurface.cxx */; }; DC73BD8A1915E5E3003FAFAD /* FBSurface.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC73BD881915E5E3003FAFAD /* FBSurface.hxx */; }; DC74D6A2138D4D7E00F05C5C /* StringParser.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC74D6A0138D4D7E00F05C5C /* StringParser.hxx */; }; - DC74E5C6198AF12700F37E36 /* CartDASHWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC74E5C4198AF12700F37E36 /* CartDASHWidget.cxx */; }; - DC74E5C7198AF12700F37E36 /* CartDASHWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC74E5C5198AF12700F37E36 /* CartDASHWidget.hxx */; }; DC79F81217A88D9E00288B91 /* Base.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC79F81017A88D9E00288B91 /* Base.cxx */; }; DC79F81317A88D9E00288B91 /* Base.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC79F81117A88D9E00288B91 /* Base.hxx */; }; DC7A24D5173B1CF600B20FE9 /* Variant.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC7A24D4173B1CF600B20FE9 /* Variant.hxx */; }; @@ -494,10 +498,6 @@ DCAAE5F11715887B0080BB82 /* CartFAWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAAE5D01715887B0080BB82 /* CartFAWidget.hxx */; }; DCAAE5F21715887B0080BB82 /* CartUAWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCAAE5D11715887B0080BB82 /* CartUAWidget.cxx */; }; DCAAE5F31715887B0080BB82 /* CartUAWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAAE5D21715887B0080BB82 /* CartUAWidget.hxx */; }; - DCACBAD01C54296300703A9B /* CartCVPlusWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCACBACE1C54296300703A9B /* CartCVPlusWidget.cxx */; }; - DCACBAD11C54296300703A9B /* CartCVPlusWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCACBACF1C54296300703A9B /* CartCVPlusWidget.hxx */; }; - DCACBAD41C54298300703A9B /* CartCVPlus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCACBAD21C54298300703A9B /* CartCVPlus.cxx */; }; - DCACBAD51C54298300703A9B /* CartCVPlus.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCACBAD31C54298300703A9B /* CartCVPlus.hxx */; }; DCAD60A81152F8BD00BC4184 /* CartDPCPlus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCAD60A61152F8BD00BC4184 /* CartDPCPlus.cxx */; }; DCAD60A91152F8BD00BC4184 /* CartDPCPlus.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAD60A71152F8BD00BC4184 /* CartDPCPlus.hxx */; }; DCB20EC71A0C506C0048F595 /* main.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCB20EC61A0C506C0048F595 /* main.cxx */; }; @@ -828,8 +828,6 @@ 2DDBEA0C0845708800812C11 /* FSNodePOSIX.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FSNodePOSIX.cxx; sourceTree = ""; }; 2DDBEAA3084578BF00812C11 /* AboutDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AboutDialog.cxx; sourceTree = ""; }; 2DDBEAA4084578BF00812C11 /* AboutDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = AboutDialog.hxx; sourceTree = ""; }; - 2DDBEAA6084578BF00812C11 /* AudioDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AudioDialog.cxx; sourceTree = ""; }; - 2DDBEAA7084578BF00812C11 /* AudioDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = AudioDialog.hxx; sourceTree = ""; }; 2DDBEAA8084578BF00812C11 /* BrowserDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BrowserDialog.cxx; sourceTree = ""; }; 2DDBEAA9084578BF00812C11 /* BrowserDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = BrowserDialog.hxx; sourceTree = ""; }; 2DDBEAAA084578BF00812C11 /* Command.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = Command.hxx; sourceTree = ""; }; @@ -860,8 +858,6 @@ 2DDBEACB084578BF00812C11 /* ScrollBarWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ScrollBarWidget.hxx; sourceTree = ""; }; 2DDBEAD0084578BF00812C11 /* TabWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TabWidget.cxx; sourceTree = ""; }; 2DDBEAD1084578BF00812C11 /* TabWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = TabWidget.hxx; sourceTree = ""; }; - 2DDBEAD2084578BF00812C11 /* VideoDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = VideoDialog.cxx; sourceTree = ""; }; - 2DDBEAD3084578BF00812C11 /* VideoDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = VideoDialog.hxx; sourceTree = ""; }; 2DDBEAD4084578BF00812C11 /* Widget.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Widget.cxx; sourceTree = ""; }; 2DDBEAD5084578BF00812C11 /* Widget.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = Widget.hxx; sourceTree = ""; }; 2DDBEB7008457B7D00812C11 /* CartUA.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CartUA.cxx; sourceTree = ""; }; @@ -972,8 +968,6 @@ DC2410E12274BDA7007A4CBF /* MinUICommandDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MinUICommandDialog.hxx; sourceTree = ""; }; DC2410E22274BDA8007A4CBF /* MinUICommandDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MinUICommandDialog.cxx; sourceTree = ""; }; DC2874061F8F2278004BF21A /* TrapArray.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TrapArray.hxx; sourceTree = ""; }; - DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDASH.cxx; sourceTree = ""; }; - DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDASH.hxx; sourceTree = ""; }; DC2AADAC194F389C0026C7A4 /* TIASurface.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TIASurface.cxx; sourceTree = ""; }; DC2AADAD194F389C0026C7A4 /* TIASurface.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TIASurface.hxx; sourceTree = ""; }; DC2AADB2194F390F0026C7A4 /* CartRamWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartRamWidget.cxx; sourceTree = ""; }; @@ -989,6 +983,18 @@ DC368F5318A2FB710084199C /* SoundSDL2.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SoundSDL2.hxx; sourceTree = ""; }; DC36D2C614CAFAB0007DC821 /* CartFA2.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartFA2.cxx; sourceTree = ""; }; DC36D2C714CAFAB0007DC821 /* CartFA2.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartFA2.hxx; sourceTree = ""; }; + DC3C9BC32469C8F700CF2D47 /* PaletteHandler.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PaletteHandler.cxx; sourceTree = ""; }; + DC3C9BC42469C8F700CF2D47 /* PaletteHandler.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PaletteHandler.hxx; sourceTree = ""; }; + DC3C9BC72469C93D00CF2D47 /* VideoAudioDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoAudioDialog.cxx; sourceTree = ""; }; + DC3C9BC82469C93D00CF2D47 /* EmulationDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulationDialog.cxx; sourceTree = ""; }; + DC3C9BC92469C93D00CF2D47 /* VideoAudioDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VideoAudioDialog.hxx; sourceTree = ""; }; + DC3C9BCA2469C93D00CF2D47 /* EmulationDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = EmulationDialog.hxx; sourceTree = ""; }; + DC3C9BCF2469C9A200CF2D47 /* CartEnhanced.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartEnhanced.cxx; sourceTree = ""; }; + DC3C9BD02469C9A200CF2D47 /* Cart3EX.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Cart3EX.hxx; sourceTree = ""; }; + DC3C9BD12469C9A200CF2D47 /* CartEnhanced.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartEnhanced.hxx; sourceTree = ""; }; + DC3C9BD22469C9A200CF2D47 /* Cart3EX.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Cart3EX.cxx; sourceTree = ""; }; + DC3C9BD72469C9C700CF2D47 /* CartEnhancedWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartEnhancedWidget.cxx; sourceTree = ""; }; + DC3C9BD82469C9C700CF2D47 /* CartEnhancedWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartEnhancedWidget.hxx; sourceTree = ""; }; DC3DAFAB1F2E233B00A64410 /* PointingDevice.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PointingDevice.hxx; sourceTree = ""; }; DC3EE83C1E2C0E6D00905161 /* adler32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adler32.c; sourceTree = ""; }; DC3EE83D1E2C0E6D00905161 /* compress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = compress.c; sourceTree = ""; }; @@ -1132,8 +1138,6 @@ DC73BD871915E5E3003FAFAD /* FBSurface.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBSurface.cxx; sourceTree = ""; }; DC73BD881915E5E3003FAFAD /* FBSurface.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FBSurface.hxx; sourceTree = ""; }; DC74D6A0138D4D7E00F05C5C /* StringParser.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StringParser.hxx; sourceTree = ""; }; - DC74E5C4198AF12700F37E36 /* CartDASHWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDASHWidget.cxx; sourceTree = ""; }; - DC74E5C5198AF12700F37E36 /* CartDASHWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDASHWidget.hxx; sourceTree = ""; }; DC79F81017A88D9E00288B91 /* Base.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Base.cxx; sourceTree = ""; }; DC79F81117A88D9E00288B91 /* Base.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Base.hxx; sourceTree = ""; }; DC7A24D4173B1CF600B20FE9 /* Variant.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Variant.hxx; sourceTree = ""; }; @@ -1234,10 +1238,6 @@ DCAAE5D01715887B0080BB82 /* CartFAWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartFAWidget.hxx; sourceTree = ""; }; DCAAE5D11715887B0080BB82 /* CartUAWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartUAWidget.cxx; sourceTree = ""; }; DCAAE5D21715887B0080BB82 /* CartUAWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartUAWidget.hxx; sourceTree = ""; }; - DCACBACE1C54296300703A9B /* CartCVPlusWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCVPlusWidget.cxx; sourceTree = ""; }; - DCACBACF1C54296300703A9B /* CartCVPlusWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartCVPlusWidget.hxx; sourceTree = ""; }; - DCACBAD21C54298300703A9B /* CartCVPlus.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCVPlus.cxx; sourceTree = ""; }; - DCACBAD31C54298300703A9B /* CartCVPlus.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartCVPlus.hxx; sourceTree = ""; }; DCAD60A61152F8BD00BC4184 /* CartDPCPlus.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDPCPlus.cxx; sourceTree = ""; }; DCAD60A71152F8BD00BC4184 /* CartDPCPlus.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDPCPlus.hxx; sourceTree = ""; }; DCB20EC61A0C506C0048F595 /* main.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cxx; sourceTree = ""; }; @@ -1589,12 +1589,8 @@ DC676A2C1729A0B000E4E73D /* CartCMWidget.hxx */, DC676A2D1729A0B000E4E73D /* CartCTYWidget.cxx */, DC676A2E1729A0B000E4E73D /* CartCTYWidget.hxx */, - DCACBACE1C54296300703A9B /* CartCVPlusWidget.cxx */, - DCACBACF1C54296300703A9B /* CartCVPlusWidget.hxx */, DCAAE5BA1715887B0080BB82 /* CartCVWidget.cxx */, DCAAE5BB1715887B0080BB82 /* CartCVWidget.hxx */, - DC74E5C4198AF12700F37E36 /* CartDASHWidget.cxx */, - DC74E5C5198AF12700F37E36 /* CartDASHWidget.hxx */, DC5ACB5D1FBFCEB800A213FD /* CartDebugWidget.cxx */, DCAAE5BC1715887B0080BB82 /* CartDebugWidget.hxx */, DCAACB0A188D636F00A4D282 /* CartDFSCWidget.cxx */, @@ -1615,6 +1611,8 @@ DCAAE5BE1715887B0080BB82 /* CartEFSCWidget.hxx */, DCAAE5BF1715887B0080BB82 /* CartEFWidget.cxx */, DCAAE5C01715887B0080BB82 /* CartEFWidget.hxx */, + DC3C9BD72469C9C700CF2D47 /* CartEnhancedWidget.cxx */, + DC3C9BD82469C9C700CF2D47 /* CartEnhancedWidget.hxx */, DCAAE5C11715887B0080BB82 /* CartF0Widget.cxx */, DCAAE5C21715887B0080BB82 /* CartF0Widget.hxx */, DCAAE5C31715887B0080BB82 /* CartF4SCWidget.cxx */, @@ -1744,6 +1742,8 @@ DCB87E571A104C1E00BF2A3B /* MediaFactory.hxx */, DC56FCDC14CCCC4900A31CC3 /* MouseControl.cxx */, DC56FCDD14CCCC4900A31CC3 /* MouseControl.hxx */, + DC3C9BC32469C8F700CF2D47 /* PaletteHandler.cxx */, + DC3C9BC42469C8F700CF2D47 /* PaletteHandler.hxx */, DCA233AE23B583FE0032ABF3 /* PhosphorHandler.cxx */, DCA233AF23B583FE0032ABF3 /* PhosphorHandler.hxx */, DC6DC91A205DB879004A5FC3 /* PhysicalJoystick.cxx */, @@ -1824,6 +1824,8 @@ 2D9555DA0880E78000466554 /* Cart3E.hxx */, DCBDDE9C1D6A5F2F009DF1E9 /* Cart3EPlus.cxx */, DCBDDE9D1D6A5F2F009DF1E9 /* Cart3EPlus.hxx */, + DC3C9BD22469C9A200CF2D47 /* Cart3EX.cxx */, + DC3C9BD02469C9A200CF2D47 /* Cart3EX.hxx */, 2DE2DF160627AE07006BEC99 /* Cart3F.cxx */, 2DE2DF170627AE07006BEC99 /* Cart3F.hxx */, DCD56D360B247D920092F9F8 /* Cart4A50.cxx */, @@ -1850,10 +1852,6 @@ DC6727091556F4860023653B /* CartCTY.hxx */, 2DE2DF1C0627AE07006BEC99 /* CartCV.cxx */, 2DE2DF1D0627AE07006BEC99 /* CartCV.hxx */, - DCACBAD21C54298300703A9B /* CartCVPlus.cxx */, - DCACBAD31C54298300703A9B /* CartCVPlus.hxx */, - DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */, - DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */, DCB2ECAC1F0AECA3009738A6 /* CartDetector.cxx */, DCB2ECAD1F0AECA3009738A6 /* CartDetector.hxx */, DCAACAF2188D631500A4D282 /* CartDF.cxx */, @@ -1874,6 +1872,8 @@ DCF467BF0F939A1400B25D7A /* CartEF.hxx */, DCF467C00F939A1400B25D7A /* CartEFSC.cxx */, DCF467C10F939A1400B25D7A /* CartEFSC.hxx */, + DC3C9BCF2469C9A200CF2D47 /* CartEnhanced.cxx */, + DC3C9BD12469C9A200CF2D47 /* CartEnhanced.hxx */, DCF7B0D910A762FC007A2870 /* CartF0.cxx */, DCF7B0DA10A762FC007A2870 /* CartF0.hxx */, 2DE2DF240627AE07006BEC99 /* CartF4.cxx */, @@ -2003,8 +2003,6 @@ children = ( 2DDBEAA3084578BF00812C11 /* AboutDialog.cxx */, 2DDBEAA4084578BF00812C11 /* AboutDialog.hxx */, - 2DDBEAA6084578BF00812C11 /* AudioDialog.cxx */, - 2DDBEAA7084578BF00812C11 /* AudioDialog.hxx */, 2DDBEAA8084578BF00812C11 /* BrowserDialog.cxx */, 2DDBEAA9084578BF00812C11 /* BrowserDialog.hxx */, 2DEF21F808BC033500B246B4 /* CheckListWidget.cxx */, @@ -2034,6 +2032,8 @@ 2D403BA1086116D1001E31A1 /* EditableWidget.hxx */, 2D403BA4086116D1001E31A1 /* EditTextWidget.cxx */, 2D403BA5086116D1001E31A1 /* EditTextWidget.hxx */, + DC3C9BC82469C93D00CF2D47 /* EmulationDialog.cxx */, + DC3C9BCA2469C93D00CF2D47 /* EmulationDialog.hxx */, 2D05FF5E096E269100A518FE /* EventMappingWidget.cxx */, 2D05FF5F096E269100A518FE /* EventMappingWidget.hxx */, DC7A24DD173B1DBC00B20FE9 /* FileListWidget.cxx */, @@ -2107,8 +2107,8 @@ DCA82C701FEB4E780059340F /* TimeMachineDialog.hxx */, DC8078E60B4BD697005E9305 /* UIDialog.cxx */, DC8078E70B4BD697005E9305 /* UIDialog.hxx */, - 2DDBEAD2084578BF00812C11 /* VideoDialog.cxx */, - 2DDBEAD3084578BF00812C11 /* VideoDialog.hxx */, + DC3C9BC72469C93D00CF2D47 /* VideoAudioDialog.cxx */, + DC3C9BC92469C93D00CF2D47 /* VideoAudioDialog.hxx */, 2DDBEAD4084578BF00812C11 /* Widget.cxx */, 2DDBEAD5084578BF00812C11 /* Widget.hxx */, ); @@ -2391,10 +2391,9 @@ DC5AAC2D1FCB24DF00C420A6 /* RadioButtonWidget.hxx in Headers */, 2D9173E309BA90380026E9FF /* Driving.hxx in Headers */, 2D9173E409BA90380026E9FF /* Event.hxx in Headers */, + DC3C9BCD2469C93D00CF2D47 /* VideoAudioDialog.hxx in Headers */, 2D9173E509BA90380026E9FF /* Joystick.hxx in Headers */, 2D9173E609BA90380026E9FF /* Keyboard.hxx in Headers */, - DCACBAD51C54298300703A9B /* CartCVPlus.hxx in Headers */, - DCACBAD11C54296300703A9B /* CartCVPlusWidget.hxx in Headers */, DC1B2EC81E50036100F62837 /* TrakBall.hxx in Headers */, 2D9173E709BA90380026E9FF /* M6532.hxx in Headers */, E0893AF3211B9842008B170D /* HighPass.hxx in Headers */, @@ -2417,7 +2416,7 @@ DCF3A6EE1DFC75E3008A8AF3 /* DelayQueueMember.hxx in Headers */, DC96162F1F817830008A2206 /* AtariMouseWidget.hxx in Headers */, DCF4907A1A0ECE5B00A67AA9 /* Vec.hxx in Headers */, - 2D91740109BA90380026E9FF /* AudioDialog.hxx in Headers */, + DC3C9BCE2469C93D00CF2D47 /* EmulationDialog.hxx in Headers */, DC71EA9E1FDA06D2008827CB /* CartE78K.hxx in Headers */, 2D91740209BA90380026E9FF /* BrowserDialog.hxx in Headers */, 2D91740309BA90380026E9FF /* Command.hxx in Headers */, @@ -2446,7 +2445,6 @@ 2D91741309BA90380026E9FF /* ScrollBarWidget.hxx in Headers */, 2D91741609BA90380026E9FF /* TabWidget.hxx in Headers */, DCB2ECB01F0AECA3009738A6 /* CartDetector.hxx in Headers */, - 2D91741709BA90380026E9FF /* VideoDialog.hxx in Headers */, 2D91741809BA90380026E9FF /* Widget.hxx in Headers */, 2D91741909BA90380026E9FF /* CartUA.hxx in Headers */, DCE8B1871E7E03B300189864 /* FrameLayout.hxx in Headers */, @@ -2476,6 +2474,7 @@ DC3EE86C1E2C0E6D00905161 /* zconf.h in Headers */, 2D91743609BA90380026E9FF /* DebuggerSystem.hxx in Headers */, 2D91743A09BA90380026E9FF /* Expression.hxx in Headers */, + DC3C9BDA2469C9C700CF2D47 /* CartEnhancedWidget.hxx in Headers */, 2D91744F09BA90380026E9FF /* InputTextDialog.hxx in Headers */, DC1B2EC61E50036100F62837 /* AtariMouse.hxx in Headers */, DC9616331F817830008A2206 /* PointingDeviceWidget.hxx in Headers */, @@ -2502,7 +2501,7 @@ DCA078351F8C1B04008EFEE5 /* SDL_lib.hxx in Headers */, DCDA03B11A2009BB00711920 /* CartWD.hxx in Headers */, 2D91745909BA90380026E9FF /* PromptWidget.hxx in Headers */, - DC2AADAF194F389C0026C7A4 /* CartDASH.hxx in Headers */, + DC3C9BC62469C8F700CF2D47 /* PaletteHandler.hxx in Headers */, 2D91745A09BA90380026E9FF /* RamWidget.hxx in Headers */, 2D91745B09BA90380026E9FF /* RomListWidget.hxx in Headers */, 2D91745C09BA90380026E9FF /* RomWidget.hxx in Headers */, @@ -2513,6 +2512,7 @@ 2D91746109BA90380026E9FF /* TogglePixelWidget.hxx in Headers */, 2D91746209BA90380026E9FF /* ToggleWidget.hxx in Headers */, 2D91746409BA90380026E9FF /* TiaZoomWidget.hxx in Headers */, + DC3C9BD52469C9A200CF2D47 /* CartEnhanced.hxx in Headers */, DC1BC6672066B4390076F74A /* PKeyboardHandler.hxx in Headers */, 2D91746609BA90380026E9FF /* AudioWidget.hxx in Headers */, DC70065E241EC97900A459AB /* Stella14x28tFont.hxx in Headers */, @@ -2593,7 +2593,6 @@ DCD6FC7111C281ED005DA767 /* png.h in Headers */, DCD6FC7211C281ED005DA767 /* pngconf.h in Headers */, DCF3A6F41DFC75E3008A8AF3 /* LatchedInput.hxx in Headers */, - DC74E5C7198AF12700F37E36 /* CartDASHWidget.hxx in Headers */, DCD6FC7711C281ED005DA767 /* pngpriv.h in Headers */, CFE3F60C1E84A9A200A8204E /* CartBUSWidget.hxx in Headers */, DCD6FC9411C28C6F005DA767 /* PNGLibrary.hxx in Headers */, @@ -2637,6 +2636,7 @@ DCE395EF16CB0B5F008DB1E5 /* FSNodeFactory.hxx in Headers */, DCE395F116CB0B5F008DB1E5 /* FSNodeZIP.hxx in Headers */, DCE395F316CB0B5F008DB1E5 /* ZipHandler.hxx in Headers */, + DC3C9BD42469C9A200CF2D47 /* Cart3EX.hxx in Headers */, DCAAE5D41715887B0080BB82 /* Cart2KWidget.hxx in Headers */, DCF7F129223D796000701A47 /* ProfilingRunner.hxx in Headers */, DCAAE5D61715887B0080BB82 /* Cart3FWidget.hxx in Headers */, @@ -2816,7 +2816,9 @@ E0A755792244294600101889 /* CartCDFInfoWidget.cxx in Sources */, E0406FB81F81A85400A82AE0 /* FrameManager.cxx in Sources */, 2D91747409BA90380026E9FF /* SDLMain.m in Sources */, + DC3C9BC52469C8F700CF2D47 /* PaletteHandler.cxx in Sources */, 2D91747509BA90380026E9FF /* Booster.cxx in Sources */, + DC3C9BD62469C9A200CF2D47 /* Cart3EX.cxx in Sources */, DC3EE8671E2C0E6D00905161 /* inftrees.c in Sources */, 2D91747609BA90380026E9FF /* Cart.cxx in Sources */, 2D91747709BA90380026E9FF /* Cart2K.cxx in Sources */, @@ -2844,6 +2846,7 @@ DCF3A6FA1DFC75E3008A8AF3 /* Player.cxx in Sources */, 2D91748609BA90380026E9FF /* CartFE.cxx in Sources */, 2D91748909BA90380026E9FF /* Console.cxx in Sources */, + DC3C9BD32469C9A200CF2D47 /* CartEnhanced.cxx in Sources */, DC6DC91E205DB879004A5FC3 /* PhysicalJoystick.cxx in Sources */, E08FCD5323A037EB0051F59B /* QisBlitter.cxx in Sources */, DCCE0355225104BF008C246F /* StellaSettingsDialog.cxx in Sources */, @@ -2867,7 +2870,6 @@ 2D9174A309BA90380026E9FF /* Settings.cxx in Sources */, 2D9174A809BA90380026E9FF /* FSNodePOSIX.cxx in Sources */, 2D9174AA09BA90380026E9FF /* AboutDialog.cxx in Sources */, - 2D9174AB09BA90380026E9FF /* AudioDialog.cxx in Sources */, 2D9174AC09BA90380026E9FF /* BrowserDialog.cxx in Sources */, 2D9174AD09BA90380026E9FF /* Dialog.cxx in Sources */, 2D9174AE09BA90380026E9FF /* DialogContainer.cxx in Sources */, @@ -2877,6 +2879,7 @@ 2D9174B309BA90380026E9FF /* LauncherDialog.cxx in Sources */, 2D9174B509BA90380026E9FF /* ListWidget.cxx in Sources */, 2D9174B609BA90380026E9FF /* Menu.cxx in Sources */, + DC3C9BD92469C9C700CF2D47 /* CartEnhancedWidget.cxx in Sources */, CFE3F60D1E84A9A200A8204E /* CartCDFWidget.cxx in Sources */, 2D9174B709BA90380026E9FF /* OptionsDialog.cxx in Sources */, 2D9174B809BA90380026E9FF /* PopUpWidget.cxx in Sources */, @@ -2886,7 +2889,6 @@ 2D9174B909BA90380026E9FF /* ProgressDialog.cxx in Sources */, 2D9174BA09BA90380026E9FF /* ScrollBarWidget.cxx in Sources */, 2D9174BB09BA90380026E9FF /* TabWidget.cxx in Sources */, - 2D9174BC09BA90380026E9FF /* VideoDialog.cxx in Sources */, DC6A18FC19B3E67A00DEB242 /* CartMDM.cxx in Sources */, 2D9174BD09BA90380026E9FF /* Widget.cxx in Sources */, 2D9174BE09BA90380026E9FF /* CartUA.cxx in Sources */, @@ -2914,7 +2916,6 @@ 2D9174F109BA90380026E9FF /* InputTextDialog.cxx in Sources */, DC6DC920205DB879004A5FC3 /* PJoystickHandler.cxx in Sources */, DC2410E42274BDA8007A4CBF /* MinUICommandDialog.cxx in Sources */, - DC74E5C6198AF12700F37E36 /* CartDASHWidget.cxx in Sources */, 2D9174F209BA90380026E9FF /* CheckListWidget.cxx in Sources */, 2D9174F309BA90380026E9FF /* StringListWidget.cxx in Sources */, 2D9174F409BA90380026E9FF /* CommandDialog.cxx in Sources */, @@ -2931,7 +2932,6 @@ DC5963132139FA14002736F2 /* Bankswitch.cxx in Sources */, DCDFF08120B781B0001227C0 /* DispatchResult.cxx in Sources */, 2D9174FC09BA90380026E9FF /* RamWidget.cxx in Sources */, - DC2AADAE194F389C0026C7A4 /* CartDASH.cxx in Sources */, DC21E5C121CA903E007D0E1A /* SerialPortMACOS.cxx in Sources */, E007231F210FBF5E002CF343 /* FpsMeter.cxx in Sources */, 2D9174FD09BA90380026E9FF /* RomListWidget.cxx in Sources */, @@ -2960,7 +2960,6 @@ DC47455A09C34BFA00EDDA3A /* CheatManager.cxx in Sources */, DC47455C09C34BFA00EDDA3A /* CheetahCheat.cxx in Sources */, DC62E6471960E87B007AEF05 /* AtariVoxWidget.cxx in Sources */, - DCACBAD41C54298300703A9B /* CartCVPlus.cxx in Sources */, DC47455E09C34BFA00EDDA3A /* RamCheat.cxx in Sources */, E0FABEEC20E9948200EB8E28 /* AudioSettings.cxx in Sources */, DCD56D380B247D920092F9F8 /* Cart4A50.cxx in Sources */, @@ -3003,6 +3002,7 @@ DC6B2BA411037FF200F199A7 /* CartDebug.cxx in Sources */, DCB20EC71A0C506C0048F595 /* main.cxx in Sources */, DC6B2BA611037FF200F199A7 /* DiStella.cxx in Sources */, + DC3C9BCB2469C93D00CF2D47 /* VideoAudioDialog.cxx in Sources */, CFE3F6151E84A9CE00A8204E /* CartCDF.cxx in Sources */, E08D2F3E23089B9B000BD709 /* JoyMap.cxx in Sources */, DCA82C711FEB4E780059340F /* TimeMachine.cxx in Sources */, @@ -3103,6 +3103,7 @@ DC676A531729A0B000E4E73D /* CartFA2Widget.cxx in Sources */, DC676A551729A0B000E4E73D /* CartFEWidget.cxx in Sources */, DC676A591729A0B000E4E73D /* CartSBWidget.cxx in Sources */, + DC3C9BCC2469C93D00CF2D47 /* EmulationDialog.cxx in Sources */, DC676A5B1729A0B000E4E73D /* CartX07Widget.cxx in Sources */, DC7A24DF173B1DBC00B20FE9 /* FileListWidget.cxx in Sources */, DC13B53F176FF2F500B8B4BB /* RomListSettings.cxx in Sources */, @@ -3116,7 +3117,6 @@ DCAACAFC188D631500A4D282 /* CartDF.cxx in Sources */, DCAACAFE188D631500A4D282 /* CartDFSC.cxx in Sources */, DCAACB0E188D636F00A4D282 /* Cart4KSCWidget.cxx in Sources */, - DCACBAD01C54296300703A9B /* CartCVPlusWidget.cxx in Sources */, DCAACB10188D636F00A4D282 /* CartBFSCWidget.cxx in Sources */, DCAACB12188D636F00A4D282 /* CartBFWidget.cxx in Sources */, DCAACB14188D636F00A4D282 /* CartDFSCWidget.cxx in Sources */, diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj index 1095f2c09..6fef5d589 100644 --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -503,6 +503,7 @@ + @@ -757,6 +758,7 @@ + @@ -906,7 +908,6 @@ true - @@ -938,7 +939,7 @@ - + CompileAsC @@ -1503,6 +1504,7 @@ + @@ -1789,6 +1791,7 @@ + @@ -1965,7 +1968,6 @@ - @@ -2001,7 +2003,7 @@ - + diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters index fb763da4c..0e4f58929 100644 --- a/src/windows/Stella.vcxproj.filters +++ b/src/windows/Stella.vcxproj.filters @@ -342,9 +342,6 @@ Source Files\gui - - Source Files\gui - Source Files\gui @@ -438,9 +435,6 @@ Source Files\gui - - Source Files\gui - Source Files\gui @@ -1002,6 +996,15 @@ Source Files\emucore + + Source Files + + + Source Files\gui + + + Source Files\gui + @@ -1313,9 +1316,6 @@ Header Files\gui - - Header Files\gui - Header Files\gui @@ -1421,9 +1421,6 @@ Header Files\gui - - Header Files\gui - Header Files\gui @@ -2057,6 +2054,15 @@ Header Files\emucore + + Header Files + + + Header Files\gui + + + Header Files\gui +