From 825c0e516a7211519d834235b05d485c03d1dc95 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Fri, 8 May 2020 17:51:19 +0200 Subject: [PATCH 01/14] refactor palette handling into own class convert brightness, contrast, saturation and gamma --- src/common/PKeyboardHandler.cxx | 3 +- src/common/PaletteHandler.cxx | 721 +++++++++++++++++++++++++++++ src/common/PaletteHandler.hxx | 155 +++++++ src/common/module.mk | 1 + src/emucore/Console.cxx | 574 +---------------------- src/emucore/Console.hxx | 82 +--- src/emucore/ConsoleTiming.hxx | 3 +- src/emucore/Event.hxx | 4 +- src/emucore/EventHandler.cxx | 19 +- src/emucore/EventHandler.hxx | 2 +- src/emucore/Settings.cxx | 2 +- src/gui/CommandDialog.cxx | 3 +- src/gui/HelpDialog.cxx | 2 +- src/gui/VideoDialog.cxx | 5 +- src/windows/Stella.vcxproj | 2 + src/windows/Stella.vcxproj.filters | 6 + 16 files changed, 925 insertions(+), 659 deletions(-) create mode 100644 src/common/PaletteHandler.cxx create mode 100644 src/common/PaletteHandler.hxx diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx index f32600345..639d8ae31 100644 --- a/src/common/PKeyboardHandler.cxx +++ b/src/common/PKeyboardHandler.cxx @@ -491,7 +491,8 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo {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::PaletteDecrease, KBDK_P, KBDM_SHIFT | KBDM_CTRL}, + {Event::PaletteIncrease, KBDK_P, KBDM_CTRL}, {Event::ColorShiftDecrease, KBDK_9, KBDM_SHIFT | KBDM_CTRL}, {Event::ColorShiftIncrease, KBDK_9, KBDM_CTRL}, {Event::ToggleInter, KBDK_I, KBDM_CTRL}, diff --git a/src/common/PaletteHandler.cxx b/src/common/PaletteHandler.cxx new file mode 100644 index 000000000..e1d71f123 --- /dev/null +++ b/src/common/PaletteHandler.cxx @@ -0,0 +1,721 @@ +//============================================================================ +// +// 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 "PaletteHandler.hxx" + +PaletteHandler::PaletteHandler(OSystem& system) + : myOSystem(system) +{ + // Load user-defined palette for this ROM + loadUserPalette(); + + //// Generate custom palette + //generateCustomPalette(ConsoleTiming::ntsc); + //generateCustomPalette(ConsoleTiming::pal); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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 +{ + string SETTING_NAMES[int(PaletteType::NumTypes)] = { + SETTING_STANDARD, SETTING_Z26, SETTING_USER, SETTING_CUSTOM + }; + + return SETTING_NAMES[type]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::changePalette(bool increase) +{ + string MESSAGES[PaletteType::NumTypes] = { + "Standard Stella", "Z26", "User-defined", "Custom" + }; + + string palette, message; + palette = myOSystem.settings().getString("palette"); + + + int type = toPaletteType(myOSystem.settings().getString("palette")); + + if(increase) + { + 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--; + } + + palette = toPaletteName(PaletteType(type)); + message = MESSAGES[type] + " palette"; + + myOSystem.frameBuffer().showMessage(message); + + setPalette(palette); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::generatePalettes() +{ + generateCustomPalette(ConsoleTiming::ntsc); + generateCustomPalette(ConsoleTiming::pal); + generateColorLossPalette(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::changeColorPhaseShift(bool increase) +{ + const char DEGREE = 0x1c; + const float NTSC_SHIFT = 26.2F; + const float PAL_SHIFT = 31.3F; // 360 / 11.5 + const ConsoleTiming timing = myOSystem.console().timing(); + const bool isNTSC = timing == ConsoleTiming::ntsc; + const bool isPAL = timing == ConsoleTiming::pal; + + // 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(increase) // increase color phase shift + { + phase += 0.3F; + phase = std::min(phase, shift + 4.5F); + } + else // decrease color phase shift + { + phase -= 0.3F; + phase = std::max(phase, shift - 4.5F); + } + myOSystem.settings().setValue(key, phase); + generateCustomPalette(timing); + + setPalette("custom"); + + ostringstream ss; + ss << "Color phase shift at " + << std::fixed << std::setprecision(1) << phase << DEGREE; + + myOSystem.frameBuffer().showMessage(ss.str()); + } +} + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::setPalette(const string& name) +{ + myOSystem.settings().setValue("palette", name); + + setPalette(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::setPalette() +{ + 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)]; + + myOSystem.frameBuffer().setTIAPalette(adjustPalette(*palette)); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::adjustPalette(const PaletteArray& palette) +{ + PaletteArray destPalette; + // Constants for saturation and gray scale calculation + const float PR = .2989F; + const float PG = .5870F; + const float PB = .1140F; + // Generate adjust table + const int ADJUST_SIZE = 256; + const int RGB_UNIT = 1 << 8; + const float RGB_OFFSET = 0.5F; + const float brightness = myBrightness * (0.5F * RGB_UNIT) + RGB_OFFSET; + const float contrast = myContrast * (0.5F * RGB_UNIT) + RGB_UNIT; + const float saturation = mySaturation + 1; + const float gamma = 1.1333F - myGamma * 0.5F; + /* match common PC's 2.2 gamma to TV's 2.65 gamma */ + const float toFloat = 1.F / (ADJUST_SIZE - 1); + 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(int 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; + + // TOOD: adjust hue (different for NTSC and PAL?) + + // adjust saturation + float P = sqrt(r * r * PR + g * g * PG + b * b * PB) ; + + r = P + (r - P) * saturation; + g = P + (g - P) * saturation; + b = P + (b - P) * saturation; + + r = BSPF::clamp(r, 0, 255); + g = BSPF::clamp(g, 0, 255); + b = BSPF::clamp(b, 0, 255); + + // 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) + 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); + 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 PaletteHandler::generateCustomPalette(ConsoleTiming timing) +{ + constexpr int NUM_CHROMA = 16; + constexpr int NUM_LUMA = 8; + constexpr float SATURATION = 0.25F; + + float color[NUM_CHROMA][2] = {{0.0F}}; + + if(timing == ConsoleTiming::ntsc) + { + // 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.2F); + G = powf(G, 1.2F); + B = powf(B, 1.2F); + + 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 PaletteHandler::changeSaturation(int& R, int& G, int& B, float change) +{ + // public-domain function by Darel Rex Finley + // + // The passed-in RGB values can be on any desired scale, such as 0 to + // to 1, or 0 to 255. (But use the same scale for all three!) + // + // The "change" parameter works like this: + // 0.0 creates a black-and-white image. + // 0.5 reduces the color saturation by half. + // 1.0 causes no change. + // 2.0 doubles the color saturation. + // Note: A "change" value greater than 1.0 may project your RGB values + // beyond their normal range, in which case you probably should truncate + // them to the desired range before trying to use them in an image. + constexpr float PR = .2989F; + constexpr float PG = .5870F; + constexpr float PB = .1140F; + + float P = sqrt(R * R * PR + G * G * PG + B * B * PB) ; + + R = P + (R - P) * change; + G = P + (G - P) * change; + B = P + (B - P) * change; + + R = BSPF::clamp(R, 0, 255); + G = BSPF::clamp(G, 0, 255); + B = BSPF::clamp(B, 0, 255); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::changeSaturation(float& R, float& G, float& B, float change) +{ + constexpr float PR = .2989F; + constexpr float PG = .5870F; + constexpr float PB = .1140F; + + float P = sqrt(R * R * PR + G * G * PG + B * B * PB) ; + + R = P + (R - P) * change; + G = P + (G - P) * change; + B = P + (B - P) * change; + + if(R < 0) R = 0; + if(G < 0) G = 0; + if(B < 0) B = 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::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) + { + int idx = PaletteType::User * int(ConsoleTiming::numTimings); + palette[idx + int(ConsoleTiming::ntsc)] = ourUserNTSCPalette.data(); + palette[idx + int(ConsoleTiming::pal)] = ourUserPALPalette.data(); + palette[idx + int(ConsoleTiming::secam)] = ourUserSECAMPalette.data(); + } + + for(int i = 0; i < int(ConsoleTiming::numTimings) * 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; + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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, +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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..6b26b918a --- /dev/null +++ b/src/common/PaletteHandler.hxx @@ -0,0 +1,155 @@ +//============================================================================ +// +// 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" + +class PaletteHandler +{ + public: + 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"; + + enum DisplayType { + NTSC, + PAL, + SECAM, + NumDisplayTypes + }; + + + public: + PaletteHandler(OSystem& system); + virtual ~PaletteHandler() = default; + + /** + Switch between the available palettes. + */ + void changePalette(bool increase = true); + + + /** + 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); + + void changeSaturation(int& R, int& G, int& B, float change); + void changeSaturation(float& R, float& G, float& B, float change); + + /** + Sets the palette according to the given palette name. + + @param palette The palette to switch to. + */ + void setPalette(const string& name); + + + /** + Sets the palette from current settings. + */ + void setPalette(); + + + void generatePalettes(); + + /** + 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(); + + + /** + Generates a custom palette, based on user defined phase shifts. + */ + void generateCustomPalette(ConsoleTiming timing); + + private: + enum PaletteType { + Standard, + Z26, + User, + Custom, + NumTypes, + MinType = Standard, + MaxType = Custom + }; + + PaletteType toPaletteType(const string& name) const; + string toPaletteName(PaletteType type) const; + + PaletteArray adjustPalette(const PaletteArray& source); + + /** + Loads a user-defined palette file (from OSystem::paletteFile), filling the + appropriate user-defined palette arrays. + */ + void loadUserPalette(); + + + private: + OSystem& myOSystem; + + // range -1.0 to +1.0 (as in AtariNTSC) + float myContrast{0.0F}; + float myBrightness{0.0F}; + float myHue{0.0F}; + float mySaturation{0.0F}; + float myGamma{0.0F}; + + // Indicates whether an external palette was found and + // successfully loaded + bool myUserPaletteDefined{false}; + + // 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: + 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/emucore/Console.cxx b/src/emucore/Console.cxx index 46078f09d..299b1ea3a 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -62,6 +62,7 @@ #include "AudioSettings.hxx" #include "frame-manager/FrameManager.hxx" #include "frame-manager/FrameLayoutDetector.hxx" +#include "PaletteHandler.hxx" #ifdef CHEATCODE_SUPPORT #include "CheatManager.hxx" @@ -81,19 +82,13 @@ 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()); myTIA = make_unique(*this, [this]() { return timing(); }, myOSystem.settings()); myFrameManager = make_unique(); mySwitches = make_unique(myEvent, myProperties, myOSystem.settings()); + myPaletteHandler = make_unique(myOSystem); myTIA->setFrameManager(myFrameManager.get()); @@ -441,7 +436,7 @@ void Console::setFormat(uInt32 format) myConsoleInfo.DisplayFormat = myDisplayFormat + autodetected; - setPalette(myOSystem.settings().getString("palette")); + myPaletteHandler->setPalette(); setTIAProperties(); initializeVideo(); // takes care of refreshing the screen initializeAudio(); // ensure that audio synthesis is set up to match emulation speed @@ -477,96 +472,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,11 +582,9 @@ FBInitStatus Console::initializeVideo(bool full) myOSystem.frameBuffer().showFrameStats( myOSystem.settings().getBool(devSettings ? "dev.stats" : "plr.stats")); - generateCustomPalette(0); - generateCustomPalette(1); - generateColorLossPalette(); + myPaletteHandler->generatePalettes(); } - setPalette(myOSystem.settings().getString("palette")); + myPaletteHandler->setPalette(); return fbstatus; } @@ -826,46 +729,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 +936,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 +1007,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..36c680539 100644 --- a/src/emucore/Console.hxx +++ b/src/emucore/Console.hxx @@ -29,6 +29,7 @@ class CompuMate; class Debugger; class AudioQueue; class AudioSettings; +class PaletteHandler; #include "bspf.hxx" #include "ConsoleIO.hxx" @@ -186,6 +187,11 @@ class Console : public Serializable, public ConsoleIO */ EmulationTiming& emulationTiming() { return myEmulationTiming; } + /** + Retrieve palette handler. + */ + PaletteHandler& paletteHandler() const { return *myPaletteHandler; } + public: /** Toggle between NTSC/PAL/SECAM (and variants) display format. @@ -204,23 +210,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 +277,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 +358,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 +411,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,24 +424,8 @@ 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; + // The palette handling + unique_ptrmyPaletteHandler; private: // Following constructors and assignment operators not supported 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..5dbb71126 100644 --- a/src/emucore/Event.hxx +++ b/src/emucore/Event.hxx @@ -100,7 +100,7 @@ class Event Unwind1Menu, Unwind10Menu, UnwindAllMenu, RewindPause, UnwindPause, - FormatDecrease, FormatIncrease, TogglePalette, ToggleColorLoss, + FormatDecrease, FormatIncrease, PaletteIncrease, ToggleColorLoss, ToggleFullScreen, VidmodeDecrease, VidmodeIncrease, VCenterDecrease, VCenterIncrease, ScanlineAdjustDecrease, ScanlineAdjustIncrease, OverscanDecrease, OverscanIncrease, @@ -120,7 +120,7 @@ class Event ToggleFrameStats, ToggleSAPortOrder, ExitGame, // add new events from here to avoid that user remapped events get overwritten - ToggleTurbo, + ToggleTurbo, PaletteDecrease, ColorShiftDecrease, ColorShiftIncrease, LastType diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index c9fa85835..04dd852d0 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" @@ -436,11 +437,11 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) return; case Event::ColorShiftDecrease: - if (pressed) myOSystem.console().changeColorPhaseShift(-1); + if (pressed) myOSystem.console().paletteHandler().changeColorPhaseShift(false); return; case Event::ColorShiftIncrease: - if (pressed) myOSystem.console().changeColorPhaseShift(+1); + if (pressed) myOSystem.console().paletteHandler().changeColorPhaseShift(); return; case Event::ToggleFullScreen: @@ -539,8 +540,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.console().paletteHandler().changePalette(false); + return; + + case Event::PaletteIncrease: + if (pressed && !repeated) myOSystem.console().paletteHandler().changePalette(); return; case Event::ToggleInter: @@ -1929,7 +1934,8 @@ 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::PaletteDecrease, "Switch to previous palette", "" }, + { Event::PaletteIncrease, "Switch to next palette", "" }, { Event::ColorShiftDecrease, "Decrease custom palette phase shift", "" }, { Event::ColorShiftIncrease, "Increase custom palette phase shift", "" }, { Event::ToggleInter, "Toggle display interpolation", "" }, @@ -2058,7 +2064,8 @@ 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::ColorShiftDecrease, Event::ColorShiftIncrease, Event::ToggleInter }; diff --git a/src/emucore/EventHandler.hxx b/src/emucore/EventHandler.hxx index 8fe4c7821..10259780a 100644 --- a/src/emucore/EventHandler.hxx +++ b/src/emucore/EventHandler.hxx @@ -468,7 +468,7 @@ class EventHandler #else PNG_SIZE = 0, #endif - EMUL_ACTIONLIST_SIZE = 149 + PNG_SIZE + COMBO_SIZE, + EMUL_ACTIONLIST_SIZE = 150 + PNG_SIZE + COMBO_SIZE, MENU_ACTIONLIST_SIZE = 18 ; diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index c1c64dd20..a8100d99d 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -64,12 +64,12 @@ Settings::Settings() setPermanent("tv.phosphor", "byrom"); setPermanent("tv.phosblend", "50"); setPermanent("tv.scanlines", "25"); - // TV options when using 'custom' mode 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"); diff --git a/src/gui/CommandDialog.cxx b/src/gui/CommandDialog.cxx index 5c734a52e..9efa56a7b 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().console().paletteHandler().changePalette(); updatePalette(); break; 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/VideoDialog.cxx b/src/gui/VideoDialog.cxx index 30b7a6ccc..606553562 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -25,6 +25,7 @@ #include "EditTextWidget.hxx" #include "PopUpWidget.hxx" #include "Console.hxx" +#include "PaletteHandler.hxx" #include "TIA.hxx" #include "Settings.hxx" #include "Widget.hxx" @@ -519,8 +520,8 @@ void VideoDialog::saveConfig() if(instance().settings().getString("palette") == "custom") { - instance().console().generateCustomPalette(0); - instance().console().generateCustomPalette(1); + instance().console().paletteHandler().generateCustomPalette(ConsoleTiming::ntsc); + instance().console().paletteHandler().generateCustomPalette(ConsoleTiming::pal); } if(vsizeChanged) diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj index 1095f2c09..bc0724d09 100644 --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -503,6 +503,7 @@ + @@ -1503,6 +1504,7 @@ + diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters index fb763da4c..62e324fa4 100644 --- a/src/windows/Stella.vcxproj.filters +++ b/src/windows/Stella.vcxproj.filters @@ -1002,6 +1002,9 @@ Source Files\emucore + + Source Files + @@ -2057,6 +2060,9 @@ Header Files\emucore + + Header Files + From 123d2ec9f6fd1c7737f8bd748c4be8787efe332d Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 9 May 2020 21:36:22 +0200 Subject: [PATCH 02/14] remove palette functionality from NTSCFilter load and save config values in PaletteHandler --- src/common/KeyMap.hxx | 1 + src/common/PKeyboardHandler.cxx | 34 +++-- src/common/PaletteHandler.cxx | 194 +++++++++++++++------------ src/common/PaletteHandler.hxx | 59 +++++--- src/common/tv_filters/AtariNTSC.cxx | 43 +++++- src/common/tv_filters/AtariNTSC.hxx | 12 ++ src/common/tv_filters/NTSCFilter.cxx | 45 ++++--- src/common/tv_filters/NTSCFilter.hxx | 8 ++ src/emucore/Console.cxx | 6 - src/emucore/Console.hxx | 10 -- src/emucore/Event.hxx | 13 +- src/emucore/EventHandler.cxx | 45 ++++++- src/emucore/EventHandler.hxx | 4 +- src/emucore/OSystem.cxx | 3 + src/emucore/Settings.cxx | 4 +- src/emucore/TIASurface.cxx | 32 +++++ src/emucore/TIASurface.hxx | 17 ++- src/gui/CommandDialog.cxx | 2 +- src/gui/VideoDialog.cxx | 59 ++++---- src/gui/Widget.hxx | 1 + 20 files changed, 389 insertions(+), 203 deletions(-) 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 639d8ae31..1a0fe6499 100644 --- a/src/common/PKeyboardHandler.cxx +++ b/src/common/PKeyboardHandler.cxx @@ -15,15 +15,7 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#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,16 +467,22 @@ 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}, diff --git a/src/common/PaletteHandler.cxx b/src/common/PaletteHandler.cxx index e1d71f123..4e61199d0 100644 --- a/src/common/PaletteHandler.cxx +++ b/src/common/PaletteHandler.cxx @@ -26,10 +26,6 @@ PaletteHandler::PaletteHandler(OSystem& system) { // Load user-defined palette for this ROM loadUserPalette(); - - //// Generate custom palette - //generateCustomPalette(ConsoleTiming::ntsc); - //generateCustomPalette(ConsoleTiming::pal); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -100,27 +96,118 @@ void PaletteHandler::changePalette(bool increase) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PaletteHandler::generatePalettes() +void PaletteHandler::selectAdjustable(bool next) { - generateCustomPalette(ConsoleTiming::ntsc); - generateCustomPalette(ConsoleTiming::pal); - generateColorLossPalette(); + if(next) + { + if(myCurrentAdjustable == NUM_ADJUSTABLES - 1) + myCurrentAdjustable = 0; + else + myCurrentAdjustable++; + } + else + { + if(myCurrentAdjustable == 0) + myCurrentAdjustable = NUM_ADJUSTABLES - 1; + else + myCurrentAdjustable--; + } + + ostringstream buf; + buf << "Palette adjustable '" << myAdjustables[myCurrentAdjustable].type + << "' selected"; + + myOSystem.frameBuffer().showMessage(buf.str()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::changeAdjustable(bool increase) +{ + + if(myCurrentAdjustable == NUM_ADJUSTABLES - 1) + changeColorPhaseShift(increase); + else + { + float newVal = (*myAdjustables[myCurrentAdjustable].value); + + if(increase) + { + newVal += 0.05F; + if(newVal > 1.0F) + newVal = 1.0F; + } + else + { + newVal -= 0.05F; + if(newVal < -1.0F) + newVal = -1.0F; + } + *myAdjustables[myCurrentAdjustable].value = newVal; + + ostringstream buf; + buf << "Custom '" << myAdjustables[myCurrentAdjustable].type + << "' set to " << int((newVal + 1.0F) * 100.0F + 0.5F) << "%"; + + myOSystem.frameBuffer().showMessage(buf.str()); + setPalette(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::loadConfig(const Settings& settings) +{ + // Load adjustables + 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.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(Adjustable& adjustable) +{ + 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.hue = scaleTo100(myHue); + adjustable.saturation = scaleTo100(mySaturation); + adjustable.contrast = scaleTo100(myContrast); + adjustable.brightness = scaleTo100(myBrightness); + adjustable.gamma = scaleTo100(myGamma); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PaletteHandler::changeColorPhaseShift(bool increase) { - const char DEGREE = 0x1c; - const float NTSC_SHIFT = 26.2F; - const float PAL_SHIFT = 31.3F; // 360 / 11.5 const ConsoleTiming timing = myOSystem.console().timing(); - const bool isNTSC = timing == ConsoleTiming::ntsc; - const bool isPAL = timing == ConsoleTiming::pal; // SECAM is not supported - if(isNTSC || isPAL) + if(timing != ConsoleTiming::secam) { - const string key = isNTSC ? "phase_ntsc" : "phase_pal"; + const char DEGREE = 0x1c; + const float NTSC_SHIFT = 26.2F; + const float PAL_SHIFT = 31.3F; // 360 / 11.5 + const bool isNTSC = timing == ConsoleTiming::ntsc; + const string key = isNTSC ? "tv.phase_ntsc" : "tv.phase_pal"; const float shift = isNTSC ? NTSC_SHIFT : PAL_SHIFT; float phase = myOSystem.settings().getFloat(key); @@ -175,6 +262,9 @@ void PaletteHandler::setPalette() // Now consider the current display format const PaletteArray* palette = palettes[paletteType][int(timing)]; + if(paletteType == PaletteType::Custom) + generateCustomPalette(timing); + myOSystem.frameBuffer().setTIAPalette(adjustPalette(*palette)); } @@ -212,15 +302,7 @@ PaletteArray PaletteHandler::adjustPalette(const PaletteArray& palette) // TOOD: adjust hue (different for NTSC and PAL?) // adjust saturation - float P = sqrt(r * r * PR + g * g * PG + b * b * PB) ; - - r = P + (r - P) * saturation; - g = P + (g - P) * saturation; - b = P + (b - P) * saturation; - - r = BSPF::clamp(r, 0, 255); - g = BSPF::clamp(g, 0, 255); - b = BSPF::clamp(b, 0, 255); + changeSaturation(r, g, b, saturation); // adjust contrast, brightness, gamma r = adjust[r]; @@ -235,6 +317,7 @@ PaletteArray PaletteHandler::adjustPalette(const PaletteArray& palette) // 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; @@ -299,7 +382,7 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) { // YIQ is YUV shifted by 33° constexpr float offset = 33 * (2 * BSPF::PI_f / 360); - const float shift = myOSystem.settings().getFloat("phase_ntsc") * + const float shift = myOSystem.settings().getFloat("tv.phase_ntsc") * (2 * BSPF::PI_f / 360); // color 0 is grayscale @@ -342,10 +425,10 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) } } } - else + else if(timing == ConsoleTiming::pal) { constexpr float offset = 180 * (2 * BSPF::PI_f / 360); - float shift = myOSystem.settings().getFloat("phase_pal") * + float shift = myOSystem.settings().getFloat("tv.phase_pal") * (2 * BSPF::PI_f / 360); constexpr float fixedShift = 22.5F * (2 * BSPF::PI_f / 360); @@ -432,63 +515,6 @@ void PaletteHandler::changeSaturation(int& R, int& G, int& B, float change) B = BSPF::clamp(B, 0, 255); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PaletteHandler::changeSaturation(float& R, float& G, float& B, float change) -{ - constexpr float PR = .2989F; - constexpr float PG = .5870F; - constexpr float PB = .1140F; - - float P = sqrt(R * R * PR + G * G * PG + B * B * PB) ; - - R = P + (R - P) * change; - G = P + (G - P) * change; - B = P + (B - P) * change; - - if(R < 0) R = 0; - if(G < 0) G = 0; - if(B < 0) B = 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PaletteHandler::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) - { - int idx = PaletteType::User * int(ConsoleTiming::numTimings); - palette[idx + int(ConsoleTiming::ntsc)] = ourUserNTSCPalette.data(); - palette[idx + int(ConsoleTiming::pal)] = ourUserPALPalette.data(); - palette[idx + int(ConsoleTiming::secam)] = ourUserSECAMPalette.data(); - } - - for(int i = 0; i < int(ConsoleTiming::numTimings) * 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; - } - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PaletteArray PaletteHandler::ourNTSCPalette = { 0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0, diff --git a/src/common/PaletteHandler.hxx b/src/common/PaletteHandler.hxx index 6b26b918a..d8e5518c0 100644 --- a/src/common/PaletteHandler.hxx +++ b/src/common/PaletteHandler.hxx @@ -36,6 +36,9 @@ class PaletteHandler NumDisplayTypes }; + struct Adjustable { + uInt32 hue, saturation, contrast, brightness, gamma; + }; public: PaletteHandler(OSystem& system); @@ -46,6 +49,14 @@ class PaletteHandler */ void changePalette(bool increase = true); + void selectAdjustable(bool next = true); + void changeAdjustable(bool increase = true); + + + void loadConfig(const Settings& settings); + void saveConfig(Settings& settings) const; + void setAdjustables(Adjustable& adjustable); + void getAdjustables(Adjustable& adjustable) const; /** Change the "phase shift" variable. @@ -56,9 +67,6 @@ class PaletteHandler */ void changeColorPhaseShift(bool increase = true); - void changeSaturation(int& R, int& G, int& B, float change); - void changeSaturation(float& R, float& G, float& B, float change); - /** Sets the palette according to the given palette name. @@ -72,17 +80,6 @@ class PaletteHandler */ void setPalette(); - - void generatePalettes(); - - /** - 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(); - - /** Generates a custom palette, based on user defined phase shifts. */ @@ -99,11 +96,16 @@ class PaletteHandler MaxType = Custom }; + float scaleFrom100(float x) const { return (x / 100.F) - 1.F; } + uInt32 scaleTo100(float x) const { return uInt32(100 * (x + 1.F)); } + PaletteType toPaletteType(const string& name) const; string toPaletteName(PaletteType type) const; PaletteArray adjustPalette(const PaletteArray& source); + void changeSaturation(int& R, int& G, int& B, float change); + /** Loads a user-defined palette file (from OSystem::paletteFile), filling the appropriate user-defined palette arrays. @@ -112,14 +114,33 @@ class PaletteHandler private: + static const int NUM_ADJUSTABLES = 6; + OSystem& myOSystem; + uInt32 myCurrentAdjustable{0}; + struct AdjustableTag { + const char* const type{nullptr}; + float* value{nullptr}; + }; + const std::array myAdjustables = + { { + { "contrast", &myContrast }, + { "brightness", &myBrightness }, + { "hue", &myHue }, + { "saturation", &mySaturation }, + { "gamma", &myGamma }, + { "phase shift", nullptr }, + } }; + // range -1.0 to +1.0 (as in AtariNTSC) - float myContrast{0.0F}; - float myBrightness{0.0F}; - float myHue{0.0F}; - float mySaturation{0.0F}; - float myGamma{0.0F}; + // Basic parameters + float myContrast{0.0F}; // -1 = dark (0.5) +1 = light (1.5) + float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees + float mySaturation{0.0F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0) + float 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 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..9e46b6426 100644 --- a/src/common/tv_filters/NTSCFilter.cxx +++ b/src/common/tv_filters/NTSCFilter.cxx @@ -140,13 +140,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 +160,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 +197,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 +215,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 +233,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/emucore/Console.cxx b/src/emucore/Console.cxx index 299b1ea3a..bf7d20abf 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -62,7 +62,6 @@ #include "AudioSettings.hxx" #include "frame-manager/FrameManager.hxx" #include "frame-manager/FrameLayoutDetector.hxx" -#include "PaletteHandler.hxx" #ifdef CHEATCODE_SUPPORT #include "CheatManager.hxx" @@ -88,7 +87,6 @@ Console::Console(OSystem& osystem, unique_ptr& cart, myTIA = make_unique(*this, [this]() { return timing(); }, myOSystem.settings()); myFrameManager = make_unique(); mySwitches = make_unique(myEvent, myProperties, myOSystem.settings()); - myPaletteHandler = make_unique(myOSystem); myTIA->setFrameManager(myFrameManager.get()); @@ -436,7 +434,6 @@ void Console::setFormat(uInt32 format) myConsoleInfo.DisplayFormat = myDisplayFormat + autodetected; - myPaletteHandler->setPalette(); setTIAProperties(); initializeVideo(); // takes care of refreshing the screen initializeAudio(); // ensure that audio synthesis is set up to match emulation speed @@ -582,10 +579,7 @@ FBInitStatus Console::initializeVideo(bool full) myOSystem.frameBuffer().showFrameStats( myOSystem.settings().getBool(devSettings ? "dev.stats" : "plr.stats")); - myPaletteHandler->generatePalettes(); } - myPaletteHandler->setPalette(); - return fbstatus; } diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx index 36c680539..ac26415d7 100644 --- a/src/emucore/Console.hxx +++ b/src/emucore/Console.hxx @@ -29,7 +29,6 @@ class CompuMate; class Debugger; class AudioQueue; class AudioSettings; -class PaletteHandler; #include "bspf.hxx" #include "ConsoleIO.hxx" @@ -40,7 +39,6 @@ class PaletteHandler; #include "FrameBufferConstants.hxx" #include "Serializable.hxx" #include "EventHandlerConstants.hxx" -#include "NTSCFilter.hxx" #include "EmulationTiming.hxx" #include "ConsoleTiming.hxx" #include "frame-manager/AbstractFrameManager.hxx" @@ -187,11 +185,6 @@ class Console : public Serializable, public ConsoleIO */ EmulationTiming& emulationTiming() { return myEmulationTiming; } - /** - Retrieve palette handler. - */ - PaletteHandler& paletteHandler() const { return *myPaletteHandler; } - public: /** Toggle between NTSC/PAL/SECAM (and variants) display format. @@ -424,9 +417,6 @@ class Console : public Serializable, public ConsoleIO // The audio settings AudioSettings& myAudioSettings; - // The palette handling - unique_ptrmyPaletteHandler; - private: // Following constructors and assignment operators not supported Console() = delete; diff --git a/src/emucore/Event.hxx b/src/emucore/Event.hxx index 5dbb71126..ae82ef810 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,16 @@ class Event Unwind1Menu, Unwind10Menu, UnwindAllMenu, RewindPause, UnwindPause, - FormatDecrease, FormatIncrease, PaletteIncrease, ToggleColorLoss, + FormatDecrease, FormatIncrease, PaletteDecrease, PaletteIncrease, ToggleColorLoss, + ColorShiftDecrease, ColorShiftIncrease, + 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 +122,7 @@ class Event ToggleCollisions, ToggleBits, ToggleFixedColors, ToggleFrameStats, ToggleSAPortOrder, ExitGame, - // add new events from here to avoid that user remapped events get overwritten - ToggleTurbo, PaletteDecrease, - ColorShiftDecrease, ColorShiftIncrease, LastType }; @@ -136,7 +137,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 04dd852d0..325438765 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -436,12 +436,28 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) if (pressed) myOSystem.console().changeScanlineAdjust(+1); return; + case Event::PreviousPaletteAttribute: + if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().selectAdjustable(false); + return; + + case Event::NextPaletteAttribute: + if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().selectAdjustable(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::ColorShiftDecrease: - if (pressed) myOSystem.console().paletteHandler().changeColorPhaseShift(false); + if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().changeColorPhaseShift(false); return; case Event::ColorShiftIncrease: - if (pressed) myOSystem.console().paletteHandler().changeColorPhaseShift(); + if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().changeColorPhaseShift(true); return; case Event::ToggleFullScreen: @@ -456,6 +472,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; @@ -541,11 +565,11 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) return; case Event::PaletteDecrease: - if (pressed && !repeated) myOSystem.console().paletteHandler().changePalette(false); + if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().paletteHandler().changePalette(false); return; case Event::PaletteIncrease: - if (pressed && !repeated) myOSystem.console().paletteHandler().changePalette(); + if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().paletteHandler().changePalette(true); return; case Event::ToggleInter: @@ -1934,22 +1958,30 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { { { Event::VCenterIncrease, "Move display down", "" }, { Event::FormatDecrease, "Decrease display format", "" }, { Event::FormatIncrease, "Increase display format", "" }, + // 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::ColorShiftDecrease, "Decrease custom palette phase shift", "" }, { Event::ColorShiftIncrease, "Increase custom palette phase shift", "" }, { 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", "" }, @@ -2066,6 +2098,9 @@ const Event::EventSet EventHandler::AudioVideoEvents = { Event::OverscanDecrease, Event::OverscanIncrease, Event::PaletteDecrease, Event::PaletteIncrease, Event::ColorShiftDecrease, Event::ColorShiftIncrease, + 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 10259780a..fd8522e5f 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 = 150 + PNG_SIZE + COMBO_SIZE, + EMUL_ACTIONLIST_SIZE = 154 + PNG_SIZE + COMBO_SIZE, MENU_ACTIONLIST_SIZE = 18 ; 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/Settings.cxx b/src/emucore/Settings.cxx index a8100d99d..a959cc255 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -46,8 +46,6 @@ Settings::Settings() setPermanent("windowedpos", Common::Point(50, 50)); setPermanent("display", 0); setPermanent("palette", "standard"); - setPermanent("phase_ntsc", "26.2"); - setPermanent("phase_pal", "31.3"); setPermanent("uimessages", "true"); // TIA specific options @@ -64,6 +62,8 @@ Settings::Settings() setPermanent("tv.phosphor", "byrom"); setPermanent("tv.phosblend", "50"); setPermanent("tv.scanlines", "25"); + 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"); diff --git a/src/emucore/TIASurface.cxx b/src/emucore/TIASurface.cxx index a13a9fd83..19e817b0d 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,9 @@ 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()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -89,6 +93,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 +194,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..9dbda5b14 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 @@ -49,6 +50,8 @@ class TIASurface */ explicit TIASurface(OSystem& system); + virtual ~TIASurface() = default; + /** Set the TIA object, which is needed for actually rendering the TIA image. */ @@ -87,6 +90,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 +113,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 +195,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/gui/CommandDialog.cxx b/src/gui/CommandDialog.cxx index 9efa56a7b..0d8729635 100644 --- a/src/gui/CommandDialog.cxx +++ b/src/gui/CommandDialog.cxx @@ -204,7 +204,7 @@ void CommandDialog::handleCommand(CommandSender* sender, int cmd, break; case kPaletteCmd: - instance().console().paletteHandler().changePalette(); + instance().frameBuffer().tiaSurface().paletteHandler().changePalette(); updatePalette(); break; diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx index 606553562..610ba18ff 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -367,8 +367,8 @@ void VideoDialog::loadConfig() instance().settings().getString("palette"), "standard"); // Custom Palette - myPhaseShiftNtsc->setValue(instance().settings().getFloat("phase_ntsc") * 10); - myPhaseShiftPal->setValue(instance().settings().getFloat("phase_pal") * 10); + myPhaseShiftNtsc->setValue(instance().settings().getFloat("tv.phase_ntsc") * 10); + myPhaseShiftPal->setValue(instance().settings().getFloat("tv.phase_pal") * 10); handlePaletteChange(); // TIA interpolation @@ -413,6 +413,15 @@ void VideoDialog::loadConfig() int preset = instance().settings().getInt("tv.filter"); handleTVModeChange(NTSCFilter::Preset(preset)); + // Palette adjustables + PaletteHandler::Adjustable paletteAdj; + instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(paletteAdj); + myTVHue->setValue(paletteAdj.hue); + myTVBright->setValue(paletteAdj.brightness); + myTVContrast->setValue(paletteAdj.contrast); + myTVSatur->setValue(paletteAdj.saturation); + myTVGamma->setValue(paletteAdj.gamma); + // TV Custom adjustables loadTVAdjustables(NTSCFilter::Preset::CUSTOM); @@ -444,8 +453,8 @@ void VideoDialog::saveConfig() myTIAPalette->getSelectedTag().toString()); // Custom Palette - instance().settings().setValue("phase_ntsc", myPhaseShiftNtsc->getValue() / 10.0); - instance().settings().setValue("phase_pal", myPhaseShiftPal->getValue() / 10.0); + instance().settings().setValue("tv.phase_ntsc", myPhaseShiftNtsc->getValue() / 10.0); + instance().settings().setValue("tv.phase_pal", myPhaseShiftPal->getValue() / 10.0); // TIA interpolation instance().settings().setValue("tia.inter", myTIAInterpolate->getState()); @@ -490,19 +499,23 @@ void VideoDialog::saveConfig() instance().settings().setValue("tv.filter", myTVMode->getSelectedTag().toString()); + // Palette adjustables + PaletteHandler::Adjustable paletteAdj; + paletteAdj.hue = myTVHue->getValue(); + paletteAdj.saturation = myTVSatur->getValue(); + paletteAdj.contrast = myTVContrast->getValue(); + paletteAdj.brightness = myTVBright->getValue(); + paletteAdj.gamma = myTVGamma->getValue(); + instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(paletteAdj); + // TV Custom adjustables - NTSCFilter::Adjustable 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); + 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", @@ -520,8 +533,8 @@ void VideoDialog::saveConfig() if(instance().settings().getString("palette") == "custom") { - instance().console().paletteHandler().generateCustomPalette(ConsoleTiming::ntsc); - instance().console().paletteHandler().generateCustomPalette(ConsoleTiming::pal); + instance().frameBuffer().tiaSurface().paletteHandler().generateCustomPalette(ConsoleTiming::ntsc); + instance().frameBuffer().tiaSurface().paletteHandler().generateCustomPalette(ConsoleTiming::pal); } if(vsizeChanged) @@ -595,15 +608,10 @@ 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); @@ -618,15 +626,10 @@ void VideoDialog::loadTVAdjustables(NTSCFilter::Preset preset) 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); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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" From fd02fb6e8658ea8b77b0ce41baaba037f39fbb63 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 9 May 2020 23:00:16 +0200 Subject: [PATCH 03/14] started refactoring VideoDialog fixed selecting adjustable in NTSCFilter --- src/common/PaletteHandler.cxx | 29 +-- src/common/PaletteHandler.hxx | 10 +- src/common/tv_filters/NTSCFilter.cxx | 9 + src/gui/VideoDialog.cxx | 286 ++++++++++++++++----------- src/gui/VideoDialog.hxx | 3 + 5 files changed, 206 insertions(+), 131 deletions(-) diff --git a/src/common/PaletteHandler.cxx b/src/common/PaletteHandler.cxx index 4e61199d0..b260842b1 100644 --- a/src/common/PaletteHandler.cxx +++ b/src/common/PaletteHandler.cxx @@ -98,20 +98,22 @@ void PaletteHandler::changePalette(bool increase) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PaletteHandler::selectAdjustable(bool next) { - if(next) - { - if(myCurrentAdjustable == NUM_ADJUSTABLES - 1) - myCurrentAdjustable = 0; - else + bool isCustomPalette = "custom" == myOSystem.settings().getString("palette"); + + do { + if(next) + { myCurrentAdjustable++; - } - else - { - if(myCurrentAdjustable == 0) - myCurrentAdjustable = NUM_ADJUSTABLES - 1; + myCurrentAdjustable %= NUM_ADJUSTABLES; + } else - myCurrentAdjustable--; - } + { + if(myCurrentAdjustable == 0) + myCurrentAdjustable = NUM_ADJUSTABLES - 1; + else + myCurrentAdjustable--; + } + } while(!isCustomPalette && myAdjustables[myCurrentAdjustable].value == nullptr); ostringstream buf; buf << "Palette adjustable '" << myAdjustables[myCurrentAdjustable].type @@ -123,8 +125,7 @@ void PaletteHandler::selectAdjustable(bool next) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PaletteHandler::changeAdjustable(bool increase) { - - if(myCurrentAdjustable == NUM_ADJUSTABLES - 1) + if(myAdjustables[myCurrentAdjustable].value == nullptr) changeColorPhaseShift(increase); else { diff --git a/src/common/PaletteHandler.hxx b/src/common/PaletteHandler.hxx index d8e5518c0..995018e1e 100644 --- a/src/common/PaletteHandler.hxx +++ b/src/common/PaletteHandler.hxx @@ -96,8 +96,8 @@ class PaletteHandler MaxType = Custom }; - float scaleFrom100(float x) const { return (x / 100.F) - 1.F; } - uInt32 scaleTo100(float x) const { return uInt32(100 * (x + 1.F)); } + float scaleFrom100(float x) const { return (x / 50.F) - 1.F; } + uInt32 scaleTo100(float x) const { return uInt32(50 * (x + 1.F)); } PaletteType toPaletteType(const string& name) const; string toPaletteName(PaletteType type) const; @@ -125,12 +125,12 @@ class PaletteHandler }; const std::array myAdjustables = { { - { "contrast", &myContrast }, - { "brightness", &myBrightness }, + { "phase shift", nullptr }, { "hue", &myHue }, { "saturation", &mySaturation }, + { "contrast", &myContrast }, + { "brightness", &myBrightness }, { "gamma", &myGamma }, - { "phase shift", nullptr }, } }; // range -1.0 to +1.0 (as in AtariNTSC) diff --git a/src/common/tv_filters/NTSCFilter.cxx b/src/common/tv_filters/NTSCFilter.cxx index 9e46b6426..8a40ddd2c 100644 --- a/src/common/tv_filters/NTSCFilter.cxx +++ b/src/common/tv_filters/NTSCFilter.cxx @@ -77,7 +77,12 @@ string NTSCFilter::setNextAdjustable() 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"; @@ -91,7 +96,11 @@ string NTSCFilter::setPreviousAdjustable() 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 diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx index 610ba18ff..bc890ede1 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -79,21 +79,14 @@ 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 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; + int xpos, ypos; // Set real dimensions setSize(57 * fontWidth + HBORDER * 2 + PopUpWidget::dropDownWidth(font) * 2, @@ -107,65 +100,69 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, _h - _th - VGAP - buttonHeight - VBORDER * 2); addTabWidget(myTab); - xpos = HBORDER; ypos = VBORDER; - ////////////////////////////////////////////////////////// - // 1) General options + addGeneralTab(); + addPaletteTab(); + addTVEffectsTab(); + + // 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); + myCenter->clearFlags(Widget::FLAG_ENABLED); +#endif +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoDialog::addGeneralTab() +{ + 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"), + swidth = fontWidth * 8 - fontWidth / 2; + WidgetArray wid; + VariantList items; + tabID = myTab->addTab(" General "); + xpos = HBORDER; ypos = VBORDER; // Video renderer - myRenderer = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, + 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 "); + 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 = 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, + 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); @@ -174,7 +171,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, // Speed mySpeed = - new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, + 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); @@ -183,7 +180,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, ypos += lineHeight + VGAP; // Use sync to vblank - myUseVSync = new CheckboxWidget(myTab, font, xpos, ypos + 1, "VSync"); + myUseVSync = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "VSync"); wid.push_back(myUseVSync); // Move over to the next column @@ -191,7 +188,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, ypos = VBORDER; // Fullscreen - myFullscreen = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fullscreen", kFullScreenChanged); + myFullscreen = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Fullscreen", kFullScreenChanged); wid.push_back(myFullscreen); ypos += lineHeight + VGAP; @@ -202,13 +199,13 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, ypos += lineHeight + VGAP;*/ // FS stretch - myUseStretch = new CheckboxWidget(myTab, font, xpos + INDENT, ypos + 1, "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 = 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); @@ -216,36 +213,120 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, // 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"); + 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"); + 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"); + 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"); + 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; +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoDialog::addPaletteTab() +{ + 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 = HBORDER, + ypos = VBORDER; + int swidth = fontWidth * 8 - fontWidth / 2; + int lwidth = _font.getStringWidth("Saturation "); + int pwidth = _font.getStringWidth("Standard"); + WidgetArray wid; + VariantList items; + + int tabID = myTab->addTab(" Palettes "); + + // 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; + + 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; + +#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(Hue, "Hue ", 0) + CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", 0) + CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", 0) + CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", 0) + CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", 0) + + // Add items for tab 2 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoDialog::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 = fontWidth * 2; + const int VGAP = fontHeight / 4; + int xpos = HBORDER, + ypos = VBORDER; + int swidth = fontWidth * 8 - fontWidth / 2; + int lwidth = _font.getStringWidth("TV Mode "); + int pwidth = _font.getStringWidth("Bad adjust"); + WidgetArray wid; + VariantList items; + int tabID = myTab->addTab(" TV Effects "); - // TV Mode items.clear(); VarList::push_back(items, "Disabled", static_cast(NTSCFilter::Preset::OFF)); VarList::push_back(items, "RGB", static_cast(NTSCFilter::Preset::RGB)); @@ -253,32 +334,25 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, 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, + 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 "); + lwidth = _font.getStringWidth("Saturation "); #define CREATE_CUSTOM_SLIDERS(obj, desc, cmd) \ myTV ## obj = \ - new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, \ + 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) @@ -288,22 +362,22 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, xpos += myTVContrast->getWidth() + fontWidth * 6; ypos = VBORDER; - lwidth = font.getStringWidth("Intensity "); + lwidth = _font.getStringWidth("Intensity "); // TV Phosphor effect - myTVPhosphor = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Phosphor for all ROMs", kPhosphorChanged); + 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; + swidth = _font.getMaxCharWidth() * 10; CREATE_CUSTOM_SLIDERS(PhosLevel, "Blend ", kPhosBlendChanged) - ypos += VGAP * 2; + ypos += VGAP * 2; // Scanline intensity and interpolation xpos -= INDENT; - myTVScanLabel = new StaticTextWidget(myTab, font, xpos, ypos, "Scanlines:"); + myTVScanLabel = new StaticTextWidget(myTab, _font, xpos, ypos, "Scanlines:"); ypos += lineHeight + VGAP / 2; xpos += INDENT; @@ -312,10 +386,10 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, // Adjustable presets xpos -= INDENT; - int cloneWidth = font.getStringWidth("Clone Bad Adjust") + 20; + int cloneWidth = _font.getStringWidth("Clone Bad Adjust") + 20; #define CREATE_CLONE_BUTTON(obj, desc) \ myClone ## obj = \ - new ButtonWidget(myTab, font, xpos, ypos, cloneWidth, buttonHeight,\ + new ButtonWidget(myTab, _font, xpos, ypos, cloneWidth, buttonHeight,\ desc, kClone ## obj ##Cmd); \ wid.push_back(myClone ## obj); \ ypos += buttonHeight + VGAP; @@ -327,22 +401,8 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, CREATE_CLONE_BUTTON(Bad, "Clone Bad adjust") CREATE_CLONE_BUTTON(Custom, "Revert") - // Add items for tab 2 + // Add items for tab 3 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 } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -531,12 +591,6 @@ void VideoDialog::saveConfig() { instance().console().setTIAProperties(); - if(instance().settings().getString("palette") == "custom") - { - instance().frameBuffer().tiaSurface().paletteHandler().generateCustomPalette(ConsoleTiming::ntsc); - instance().frameBuffer().tiaSurface().paletteHandler().generateCustomPalette(ConsoleTiming::pal); - } - if(vsizeChanged) { instance().console().tia().clearFrameBuffer(); @@ -560,9 +614,6 @@ void VideoDialog::setDefaults() { myRenderer->setSelectedIndex(0); myTIAZoom->setValue(300); - myTIAPalette->setSelected("standard", ""); - myPhaseShiftNtsc->setValue(262); - myPhaseShiftPal->setValue(313); myTIAInterpolate->setState(false); myVSizeAdjust->setValue(0); mySpeed->setValue(0); @@ -580,7 +631,18 @@ void VideoDialog::setDefaults() break; } - case 1: // TV effects + case 1: // Palettes + myTIAPalette->setSelected("standard", ""); + myPhaseShiftNtsc->setValue(262); + myPhaseShiftPal->setValue(313); + myTVHue->setValue(50); + myTVSatur->setValue(50); + myTVContrast->setValue(50); + myTVBright->setValue(50); + myTVGamma->setValue(50); + break; + + case 2: // TV effects { myTVMode->setSelected("0", "0"); diff --git a/src/gui/VideoDialog.hxx b/src/gui/VideoDialog.hxx index 429290082..459990e13 100644 --- a/src/gui/VideoDialog.hxx +++ b/src/gui/VideoDialog.hxx @@ -43,6 +43,9 @@ class VideoDialog : public Dialog void saveConfig() override; void setDefaults() override; + void addGeneralTab(); + void addPaletteTab(); + void addTVEffectsTab(); void handleTVModeChange(NTSCFilter::Preset); void loadTVAdjustables(NTSCFilter::Preset preset); void handlePaletteChange(); From b21efb62696425ef47106bd37b449165399b15cb Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 10 May 2020 12:46:54 +0200 Subject: [PATCH 04/14] improved VideoDialog alignment moved "Center Windows" to UIDialog --- src/gui/UIDialog.cxx | 45 ++++++++----- src/gui/UIDialog.hxx | 3 +- src/gui/VideoDialog.cxx | 136 +++++++++++++++++----------------------- src/gui/VideoDialog.hxx | 4 +- 4 files changed, 95 insertions(+), 93 deletions(-) diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 099886b9b..94032a4ce 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,9 +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; + + // Center window (in windowed mode) + xpos = myHidpiWidget->getLeft(); + myCenter = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Center windows"); + wid.push_back(myCenter); // Confirm dialog when exiting emulation + xpos = HBORDER; ypos += lineHeight + VGAP * 2; myConfirmExitWidget = new CheckboxWidget(myTab, font, xpos, ypos, "Confirm exiting emulation"); wid.push_back(myConfirmExitWidget); ypos += lineHeight + VGAP * 3; @@ -303,6 +309,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 +363,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 +378,15 @@ 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")); + + // Confirm dialog when exiting emulation + myConfirmExitWidget->setState(settings.getBool("confirmexit")); + // Listwidget quick delay int delay = settings.getInt("listdelay"); myListDelaySlider->setValue(delay); @@ -436,16 +449,19 @@ 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()); + // Center window + settings.setValue("center", myCenter->getState()); + // Confirm dialog when exiting emulation settings.setValue("confirmexit", myConfirmExitWidget->getState()); @@ -481,9 +497,10 @@ void UIDialog::setDefaults() { case 0: // Misc. options myPalettePopup->setSelected("standard"); - myHidpiWidget->setState(false); myDialogFontPopup->setSelected("medium", ""); + myHidpiWidget->setState(false); myPositionPopup->setSelected("0"); + myCenter->setState(false); myConfirmExitWidget->setState(false); myListDelaySlider->setValue(300); myWheelLinesSlider->setValue(4); diff --git a/src/gui/UIDialog.hxx b/src/gui/UIDialog.hxx index 83851e971..91bc7ff82 100644 --- a/src/gui/UIDialog.hxx +++ b/src/gui/UIDialog.hxx @@ -66,9 +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* myCenter{nullptr}; CheckboxWidget* myConfirmExitWidget{nullptr}; SliderWidget* myListDelaySlider{nullptr}; SliderWidget* myWheelLinesSlider{nullptr}; diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx index bc890ede1..26ed93a33 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -115,7 +115,8 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, // Disable certain functions when we know they aren't present #ifndef WINDOWED_SUPPORT myFullscreen->clearFlags(Widget::FLAG_ENABLED); - myCenter->clearFlags(Widget::FLAG_ENABLED); + myUseStretch->clearFlags(Widget::FLAG_ENABLED); + myTVOverscan->clearFlags(Widget::FLAG_ENABLED); #endif } @@ -129,17 +130,14 @@ void VideoDialog::addGeneralTab() 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"), - swidth = fontWidth * 8 - fontWidth / 2; + const int INDENT = CheckboxWidget::prefixSize(_font); + const int lwidth = _font.getStringWidth("V-Size adjust "), + pwidth = _font.getStringWidth("XXXXxXXXX"); + int xpos = HBORDER, + ypos = VBORDER; WidgetArray wid; VariantList items; - - tabID = myTab->addTab(" General "); - xpos = HBORDER; ypos = VBORDER; + const int tabID = myTab->addTab(" General "); // Video renderer myRenderer = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight, @@ -150,8 +148,32 @@ void VideoDialog::addGeneralTab() // TIA interpolation myTIAInterpolate = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Interpolation "); - wid.push_back(myTIAInterpolate); ypos += lineHeight + VGAP; + wid.push_back(myTIAInterpolate); ypos += lineHeight + VGAP * 4; + // 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 + const int swidth = myRenderer->getWidth() - lwidth; + 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; // TIA zoom levels (will be dynamically filled later) myTIAZoom = new SliderWidget(myTab, _font, xpos, ypos - 1, swidth, lineHeight, @@ -160,14 +182,14 @@ void VideoDialog::addGeneralTab() wid.push_back(myTIAZoom); ypos += lineHeight + VGAP; - // Aspect ratio (NTSC mode) + // 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); - ypos += lineHeight + VGAP; + ypos += lineHeight + VGAP * 4; // Speed mySpeed = @@ -187,30 +209,6 @@ void VideoDialog::addGeneralTab() 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"); @@ -222,11 +220,6 @@ void VideoDialog::addGeneralTab() 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); @@ -246,15 +239,13 @@ void VideoDialog::addPaletteTab() 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; - int swidth = fontWidth * 8 - fontWidth / 2; - int lwidth = _font.getStringWidth("Saturation "); - int pwidth = _font.getStringWidth("Standard"); WidgetArray wid; VariantList items; - - int tabID = myTab->addTab(" Palettes "); + const int tabID = myTab->addTab(" Palettes "); // TIA Palette items.clear(); @@ -268,9 +259,9 @@ void VideoDialog::addPaletteTab() wid.push_back(myTIAPalette); ypos += lineHeight + VGAP; - swidth = myTIAPalette->getWidth() - lwidth; - int plWidth = _font.getStringWidth("NTSC phase "); - int pswidth = swidth - INDENT + lwidth - plWidth; + 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, @@ -316,16 +307,15 @@ void VideoDialog::addTVEffectsTab() buttonHeight = _font.getLineHeight() * 1.25; const int VBORDER = fontHeight / 2; const int HBORDER = fontWidth * 1.25; - const int INDENT = fontWidth * 2; + const int INDENT = CheckboxWidget::prefixSize(_font);// fontWidth * 2; const int VGAP = fontHeight / 4; int xpos = HBORDER, ypos = VBORDER; - int swidth = fontWidth * 8 - fontWidth / 2; - int lwidth = _font.getStringWidth("TV Mode "); - int pwidth = _font.getStringWidth("Bad adjust"); + const int lwidth = _font.getStringWidth("Saturation "); + const int pwidth = _font.getStringWidth("Bad adjust "); WidgetArray wid; VariantList items; - int tabID = myTab->addTab(" TV Effects "); + const int tabID = myTab->addTab(" TV Effects "); items.clear(); VarList::push_back(items, "Disabled", static_cast(NTSCFilter::Preset::OFF)); @@ -334,15 +324,14 @@ void VideoDialog::addTVEffectsTab() 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 ", lwidth, kTVModeChanged); + 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) - xpos += INDENT - 2; ypos += 0; - lwidth = _font.getStringWidth("Saturation "); + const int swidth = myTVMode->getWidth() - INDENT - lwidth; + xpos += INDENT; #define CREATE_CUSTOM_SLIDERS(obj, desc, cmd) \ myTV ## obj = \ @@ -359,10 +348,9 @@ void VideoDialog::addTVEffectsTab() CREATE_CUSTOM_SLIDERS(Fringe, "Fringing ", 0) CREATE_CUSTOM_SLIDERS(Bleed, "Bleeding ", 0) - xpos += myTVContrast->getWidth() + fontWidth * 6; - ypos = VBORDER; + ypos += VGAP * 3; - lwidth = _font.getStringWidth("Intensity "); + xpos = HBORDER; // TV Phosphor effect myTVPhosphor = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Phosphor for all ROMs", kPhosphorChanged); @@ -371,9 +359,8 @@ void VideoDialog::addTVEffectsTab() // TV Phosphor blend level xpos += INDENT; - swidth = _font.getMaxCharWidth() * 10; - CREATE_CUSTOM_SLIDERS(PhosLevel, "Blend ", kPhosBlendChanged) - ypos += VGAP * 2; + CREATE_CUSTOM_SLIDERS(PhosLevel, "Blend", kPhosBlendChanged) + ypos += VGAP; // Scanline intensity and interpolation xpos -= INDENT; @@ -381,12 +368,14 @@ void VideoDialog::addTVEffectsTab() ypos += lineHeight + VGAP / 2; xpos += INDENT; - CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity ", kScanlinesChanged) - ypos += VGAP * 3; + CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity", kScanlinesChanged) + + // Create buttons in 2nd column + xpos = myTVSharp->getRight() + fontWidth * 2; + ypos = VBORDER - VGAP / 2; // Adjustable presets - xpos -= INDENT; - int cloneWidth = _font.getStringWidth("Clone Bad Adjust") + 20; + 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,\ @@ -458,9 +447,6 @@ void VideoDialog::loadConfig() // 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")); @@ -544,9 +530,6 @@ void VideoDialog::saveConfig() // 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()); @@ -623,7 +606,6 @@ void VideoDialog::setDefaults() myUseStretch->setState(false); myUseVSync->setState(true); myUIMessages->setState(true); - myCenter->setState(false); myFastSCBios->setState(true); myUseThreads->setState(false); diff --git a/src/gui/VideoDialog.hxx b/src/gui/VideoDialog.hxx index 459990e13..d780a508f 100644 --- a/src/gui/VideoDialog.hxx +++ b/src/gui/VideoDialog.hxx @@ -22,6 +22,7 @@ class CommandSender; class CheckboxWidget; class DialogContainer; class PopUpWidget; +class RadioButtonGroup; class SliderWidget; class StaticTextWidget; class TabWidget; @@ -67,13 +68,13 @@ class VideoDialog : public Dialog SliderWidget* myVSizeAdjust{nullptr}; SliderWidget* mySpeed{nullptr}; + RadioButtonGroup* myZoomGroup{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}; @@ -112,6 +113,7 @@ class VideoDialog : public Dialog kSpeedupChanged = 'VDSp', kVSizeChanged = 'VDVs', kFullScreenChanged = 'VDFs', + kZoomChanged = 'VDZo', kOverscanChanged = 'VDOv', kTVModeChanged = 'VDtv', From 85f438f6930f04e61deaad46178e531782a461b9 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 10 May 2020 19:53:59 +0200 Subject: [PATCH 05/14] added interactive palette display to VideoDialog --- src/common/PaletteHandler.cxx | 147 +++++++++++++----------- src/common/PaletteHandler.hxx | 26 +++-- src/gui/ColorWidget.cxx | 18 ++- src/gui/ColorWidget.hxx | 3 +- src/gui/VideoDialog.cxx | 210 ++++++++++++++++++++++++---------- src/gui/VideoDialog.hxx | 12 ++ 6 files changed, 274 insertions(+), 142 deletions(-) diff --git a/src/common/PaletteHandler.cxx b/src/common/PaletteHandler.cxx index b260842b1..e6bce1494 100644 --- a/src/common/PaletteHandler.cxx +++ b/src/common/PaletteHandler.cxx @@ -46,7 +46,7 @@ PaletteHandler::PaletteType PaletteHandler::toPaletteType(const string& name) co // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string PaletteHandler::toPaletteName(PaletteType type) const { - string SETTING_NAMES[int(PaletteType::NumTypes)] = { + const string SETTING_NAMES[int(PaletteType::NumTypes)] = { SETTING_STANDARD, SETTING_Z26, SETTING_USER, SETTING_CUSTOM }; @@ -56,7 +56,7 @@ string PaletteHandler::toPaletteName(PaletteType type) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PaletteHandler::changePalette(bool increase) { - string MESSAGES[PaletteType::NumTypes] = { + const string MESSAGES[PaletteType::NumTypes] = { "Standard Stella", "Z26", "User-defined", "Custom" }; @@ -98,7 +98,7 @@ void PaletteHandler::changePalette(bool increase) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PaletteHandler::selectAdjustable(bool next) { - bool isCustomPalette = "custom" == myOSystem.settings().getString("palette"); + const bool isCustomPalette = "custom" == myOSystem.settings().getString("palette"); do { if(next) @@ -154,10 +154,54 @@ void PaletteHandler::changeAdjustable(bool increase) } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::changeColorPhaseShift(bool increase) +{ + const ConsoleTiming timing = myOSystem.console().timing(); + + // SECAM is not supported + if(timing != ConsoleTiming::secam) + { + constexpr char DEGREE = 0x1c; + const bool isNTSC = timing == ConsoleTiming::ntsc; + const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT; + float phase = isNTSC ? myPhaseNTSC : myPhasePAL; + + if(increase) // increase color phase shift + { + phase += 0.3F; + phase = std::min(phase, shift + MAX_SHIFT); + } + else // decrease color phase shift + { + phase -= 0.3F; + phase = std::max(phase, shift - MAX_SHIFT); + } + if(isNTSC) + myPhaseNTSC = phase; + else + myPhasePAL = phase; + + generateCustomPalette(timing); + setPalette("custom"); + + ostringstream ss; + ss << "Color phase shift at " + << std::fixed << std::setprecision(1) << phase << DEGREE; + + myOSystem.frameBuffer().showMessage(ss.str()); + } +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PaletteHandler::loadConfig(const Settings& settings) { // Load adjustables + myPhaseNTSC = BSPF::clamp(settings.getFloat("tv.phase_ntsc"), + DEF_NTSC_SHIFT - MAX_SHIFT, DEF_NTSC_SHIFT + MAX_SHIFT); + myPhasePAL = BSPF::clamp(settings.getFloat("tv.phase_pal"), + DEF_PAL_SHIFT - MAX_SHIFT, DEF_PAL_SHIFT + MAX_SHIFT); + myHue = BSPF::clamp(settings.getFloat("tv.hue"), -1.0F, 1.0F); mySaturation = BSPF::clamp(settings.getFloat("tv.saturation"), -1.0F, 1.0F); myContrast = BSPF::clamp(settings.getFloat("tv.contrast"), -1.0F, 1.0F); @@ -169,6 +213,9 @@ void PaletteHandler::loadConfig(const Settings& settings) void PaletteHandler::saveConfig(Settings& settings) const { // Save adjustables + settings.setValue("tv.phase_ntsc", myPhaseNTSC); + settings.setValue("tv.phase_pal", myPhasePAL); + settings.setValue("tv.hue", myHue); settings.setValue("tv.saturation", mySaturation); settings.setValue("tv.contrast", myContrast); @@ -177,8 +224,11 @@ void PaletteHandler::saveConfig(Settings& settings) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PaletteHandler::setAdjustables(Adjustable& adjustable) +void PaletteHandler::setAdjustables(const Adjustable& adjustable) { + myPhaseNTSC = adjustable.phaseNtsc / 10.F; + myPhasePAL = adjustable.phasePal / 10.F; + myHue = scaleFrom100(adjustable.hue); mySaturation = scaleFrom100(adjustable.saturation); myContrast = scaleFrom100(adjustable.contrast); @@ -189,6 +239,9 @@ void PaletteHandler::setAdjustables(Adjustable& adjustable) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PaletteHandler::getAdjustables(Adjustable& adjustable) const { + adjustable.phaseNtsc = myPhaseNTSC * 10.F; + adjustable.phasePal = myPhasePAL * 10.F; + adjustable.hue = scaleTo100(myHue); adjustable.saturation = scaleTo100(mySaturation); adjustable.contrast = scaleTo100(myContrast); @@ -196,46 +249,6 @@ void PaletteHandler::getAdjustables(Adjustable& adjustable) const adjustable.gamma = scaleTo100(myGamma); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PaletteHandler::changeColorPhaseShift(bool increase) -{ - const ConsoleTiming timing = myOSystem.console().timing(); - - // SECAM is not supported - if(timing != ConsoleTiming::secam) - { - const char DEGREE = 0x1c; - const float NTSC_SHIFT = 26.2F; - const float PAL_SHIFT = 31.3F; // 360 / 11.5 - const bool isNTSC = timing == ConsoleTiming::ntsc; - const string key = isNTSC ? "tv.phase_ntsc" : "tv.phase_pal"; - const float shift = isNTSC ? NTSC_SHIFT : PAL_SHIFT; - float phase = myOSystem.settings().getFloat(key); - - if(increase) // increase color phase shift - { - phase += 0.3F; - phase = std::min(phase, shift + 4.5F); - } - else // decrease color phase shift - { - phase -= 0.3F; - phase = std::max(phase, shift - 4.5F); - } - myOSystem.settings().setValue(key, phase); - generateCustomPalette(timing); - - setPalette("custom"); - - ostringstream ss; - ss << "Color phase shift at " - << std::fixed << std::setprecision(1) << phase << DEGREE; - - myOSystem.frameBuffer().showMessage(ss.str()); - } -} - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PaletteHandler::setPalette(const string& name) { @@ -251,7 +264,7 @@ void PaletteHandler::setPalette() // Look at all the palettes, since we don't know which one is // currently active - static constexpr BSPF::array2D palettes = {{ + static constexpr BSPF::array2D palettes = {{ { &ourNTSCPalette, &ourPALPalette, &ourSECAMPalette }, { &ourNTSCPaletteZ26, &ourPALPaletteZ26, &ourSECAMPaletteZ26 }, { &ourUserNTSCPalette, &ourUserPALPalette, &ourUserSECAMPalette }, @@ -274,19 +287,19 @@ PaletteArray PaletteHandler::adjustPalette(const PaletteArray& palette) { PaletteArray destPalette; // Constants for saturation and gray scale calculation - const float PR = .2989F; - const float PG = .5870F; - const float PB = .1140F; + constexpr float PR = .2989F; + constexpr float PG = .5870F; + constexpr float PB = .1140F; // Generate adjust table - const int ADJUST_SIZE = 256; - const int RGB_UNIT = 1 << 8; - const float RGB_OFFSET = 0.5F; + constexpr int ADJUST_SIZE = 256; + constexpr int RGB_UNIT = 1 << 8; + constexpr float RGB_OFFSET = 0.5F; const float brightness = myBrightness * (0.5F * RGB_UNIT) + RGB_OFFSET; const float contrast = myContrast * (0.5F * RGB_UNIT) + RGB_UNIT; const float saturation = mySaturation + 1; const float gamma = 1.1333F - myGamma * 0.5F; /* match common PC's 2.2 gamma to TV's 2.65 gamma */ - const float toFloat = 1.F / (ADJUST_SIZE - 1); + constexpr float toFloat = 1.F / (ADJUST_SIZE - 1); std::array adjust; for(int i = 0; i < ADJUST_SIZE; i++) @@ -341,13 +354,13 @@ void PaletteHandler::loadUserPalette() for(int i = 0; i < 128; i++) // NTSC palette { in.read(reinterpret_cast(pixbuf.data()), 3); - uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); + const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); ourUserNTSCPalette[(i<<1)] = pixel; } for(int i = 0; i < 128; i++) // PAL palette { in.read(reinterpret_cast(pixbuf.data()), 3); - uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); + const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); ourUserPALPalette[(i<<1)] = pixel; } @@ -355,7 +368,7 @@ void PaletteHandler::loadUserPalette() for(int i = 0; i < 8; i++) // SECAM palette { in.read(reinterpret_cast(pixbuf.data()), 3); - uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); + const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); secam[(i<<1)] = pixel; secam[(i<<1)+1] = 0; } @@ -383,8 +396,7 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) { // YIQ is YUV shifted by 33° constexpr float offset = 33 * (2 * BSPF::PI_f / 360); - const float shift = myOSystem.settings().getFloat("tv.phase_ntsc") * - (2 * BSPF::PI_f / 360); + const float shift = myPhaseNTSC * (2 * BSPF::PI_f / 360); // color 0 is grayscale for(int chroma = 1; chroma < NUM_CHROMA; chroma++) @@ -429,8 +441,7 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) else if(timing == ConsoleTiming::pal) { constexpr float offset = 180 * (2 * BSPF::PI_f / 360); - float shift = myOSystem.settings().getFloat("tv.phase_pal") * - (2 * BSPF::PI_f / 360); + const float shift = myPhasePAL * (2 * BSPF::PI_f / 360); constexpr float fixedShift = 22.5F * (2 * BSPF::PI_f / 360); // colors 0, 1, 14 and 15 are grayscale @@ -453,11 +464,10 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) { const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90 - // Most sources + // Most sources float R = Y + 1.403F * V; float G = Y - 0.344F * U - 0.714F * V; float B = Y + 1.770F * U; - // German Wikipedia, huh??? //float B = Y + 1 / 0.493 * U; //float R = Y + 1 / 0.877 * V; @@ -504,8 +514,7 @@ void PaletteHandler::changeSaturation(int& R, int& G, int& B, float change) constexpr float PR = .2989F; constexpr float PG = .5870F; constexpr float PB = .1140F; - - float P = sqrt(R * R * PR + G * G * PG + B * B * PB) ; + const float P = sqrt(R * R * PR + G * G * PG + B * B * PB) ; R = P + (R - P) * change; G = P + (G - P) * change; @@ -517,7 +526,7 @@ void PaletteHandler::changeSaturation(int& R, int& G, int& B, float change) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray PaletteHandler::ourNTSCPalette = { +const PaletteArray PaletteHandler::ourNTSCPalette = { 0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0, 0xaaaaaa, 0, 0xc0c0c0, 0, 0xd6d6d6, 0, 0xececec, 0, 0x484800, 0, 0x69690f, 0, 0x86861d, 0, 0xa2a22a, 0, @@ -553,7 +562,7 @@ PaletteArray PaletteHandler::ourNTSCPalette = { }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray PaletteHandler::ourPALPalette = { +const PaletteArray PaletteHandler::ourPALPalette = { 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 180 0 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, // was 0x111111..0xcccccc 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 198 1 @@ -589,7 +598,7 @@ PaletteArray PaletteHandler::ourPALPalette = { }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray PaletteHandler::ourSECAMPalette = { +const PaletteArray PaletteHandler::ourSECAMPalette = { 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, @@ -625,7 +634,7 @@ PaletteArray PaletteHandler::ourSECAMPalette = { }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray PaletteHandler::ourNTSCPaletteZ26 = { +const PaletteArray PaletteHandler::ourNTSCPaletteZ26 = { 0x000000, 0, 0x505050, 0, 0x646464, 0, 0x787878, 0, 0x8c8c8c, 0, 0xa0a0a0, 0, 0xb4b4b4, 0, 0xc8c8c8, 0, 0x445400, 0, 0x586800, 0, 0x6c7c00, 0, 0x809000, 0, @@ -661,7 +670,7 @@ PaletteArray PaletteHandler::ourNTSCPaletteZ26 = { }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray PaletteHandler::ourPALPaletteZ26 = { +const PaletteArray PaletteHandler::ourPALPaletteZ26 = { 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0, 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, @@ -697,7 +706,7 @@ PaletteArray PaletteHandler::ourPALPaletteZ26 = { }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray PaletteHandler::ourSECAMPaletteZ26 = { +const PaletteArray PaletteHandler::ourSECAMPaletteZ26 = { 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, diff --git a/src/common/PaletteHandler.hxx b/src/common/PaletteHandler.hxx index 995018e1e..7c0f69dfc 100644 --- a/src/common/PaletteHandler.hxx +++ b/src/common/PaletteHandler.hxx @@ -20,6 +20,7 @@ #include "bspf.hxx" #include "OSystem.hxx" +#include "ConsoleTiming.hxx" class PaletteHandler { @@ -29,6 +30,10 @@ class PaletteHandler static constexpr const char* SETTING_USER = "user"; static constexpr const char* SETTING_CUSTOM = "custom"; + static constexpr float DEF_NTSC_SHIFT = 26.2F; + static constexpr float DEF_PAL_SHIFT = 31.3F; // 360 / 11.5 + static constexpr float MAX_SHIFT = 4.5F; + enum DisplayType { NTSC, PAL, @@ -37,6 +42,7 @@ class PaletteHandler }; struct Adjustable { + float phaseNtsc, phasePal; uInt32 hue, saturation, contrast, brightness, gamma; }; @@ -55,7 +61,7 @@ class PaletteHandler void loadConfig(const Settings& settings); void saveConfig(Settings& settings) const; - void setAdjustables(Adjustable& adjustable); + void setAdjustables(const Adjustable& adjustable); void getAdjustables(Adjustable& adjustable) const; /** @@ -114,7 +120,7 @@ class PaletteHandler private: - static const int NUM_ADJUSTABLES = 6; + static constexpr int NUM_ADJUSTABLES = 6; OSystem& myOSystem; @@ -133,11 +139,13 @@ class PaletteHandler { "gamma", &myGamma }, } }; + float myPhaseNTSC{0.0F}; + float myPhasePAL{0.0F}; // range -1.0 to +1.0 (as in AtariNTSC) // Basic parameters - float myContrast{0.0F}; // -1 = dark (0.5) +1 = light (1.5) float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees float mySaturation{0.0F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0) + float myContrast{0.0F}; // -1 = dark (0.5) +1 = light (1.5) float myBrightness{0.0F}; // -1 = dark (0.5) +1 = light (1.5) // Advanced parameters float myGamma{0.0F}; // -1 = dark (1.5) +1 = light (0.5) @@ -147,14 +155,14 @@ class PaletteHandler bool myUserPaletteDefined{false}; // Table of RGB values for NTSC, PAL and SECAM - static PaletteArray ourNTSCPalette; - static PaletteArray ourPALPalette; - static PaletteArray ourSECAMPalette; + static const PaletteArray ourNTSCPalette; + static const PaletteArray ourPALPalette; + static const PaletteArray ourSECAMPalette; // Table of RGB values for NTSC, PAL and SECAM - Z26 version - static PaletteArray ourNTSCPaletteZ26; - static PaletteArray ourPALPaletteZ26; - static PaletteArray ourSECAMPaletteZ26; + static const PaletteArray ourNTSCPaletteZ26; + static const PaletteArray ourPALPaletteZ26; + static const PaletteArray ourSECAMPaletteZ26; // Table of RGB values for NTSC, PAL and SECAM - user-defined static PaletteArray ourUserNTSCPalette; diff --git a/src/gui/ColorWidget.cxx b/src/gui/ColorWidget.cxx index 6aa58a049..8052bf029 100644 --- a/src/gui/ColorWidget.cxx +++ b/src/gui/ColorWidget.cxx @@ -25,10 +25,11 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ColorWidget::ColorWidget(GuiObject* boss, const GUI::Font& font, - int x, int y, int w, int h, int cmd) + int x, int y, int w, int h, int cmd, bool framed) : Widget(boss, font, x, y, w, h), CommandSender(boss), - _cmd(cmd) + _cmd(cmd), + _framed(framed) { _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS; } @@ -46,11 +47,18 @@ void ColorWidget::drawWidget(bool hilite) FBSurface& s = dialog().surface(); bool onTop = _boss->dialog().isOnTop(); + if(_framed) + { // Draw a thin frame around us. - s.frameRect(_x, _y, _w, _h + 1, kColor); + s.frameRect(_x, _y, _w, _h + 1, kColor); - // Show the currently selected color - s.fillRect(_x+1, _y+1, _w-2, _h-1, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo); + // Show the currently selected color + s.fillRect(_x + 1, _y + 1, _w - 2, _h - 1, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo); + } + else + { + s.fillRect(_x, _y, _w, _h, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo); + } // Cross out the grid? if(_crossGrid) 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/VideoDialog.cxx b/src/gui/VideoDialog.cxx index 26ed93a33..41460d9ba 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -18,12 +18,14 @@ #include #include "bspf.hxx" +#include "Base.hxx" #include "Control.hxx" #include "Dialog.hxx" #include "Menu.hxx" #include "OSystem.hxx" #include "EditTextWidget.hxx" #include "PopUpWidget.hxx" +#include "ColorWidget.hxx" #include "Console.hxx" #include "PaletteHandler.hxx" #include "TIA.hxx" @@ -104,6 +106,14 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, addPaletteTab(); addTVEffectsTab(); + //const int req_w = std::max(myFastSCBios->getRight(), myCloneBad->getRight()) + HBORDER + 1; + //const int req_h = _th + VGAP * 3 + // + std::max(myUseVSync->getBottom(), myTVScanIntense->getBottom()) + // + buttonHeight + VBORDER * 2; + //// Set real dimensions + //setSize(req_w, req_h, max_w, max_h); + + // Add Defaults, OK and Cancel buttons WidgetArray wid; addDefaultsOKCancelBGroup(wid, _font); @@ -266,7 +276,8 @@ void VideoDialog::addPaletteTab() myPhaseShiftNtsc = new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight, "NTSC phase", plWidth, kNtscShiftChanged, fontWidth * 5); - myPhaseShiftNtsc->setMinValue(262 - 45); myPhaseShiftNtsc->setMaxValue(262 + 45); + myPhaseShiftNtsc->setMinValue((PaletteHandler::DEF_NTSC_SHIFT - PaletteHandler::MAX_SHIFT) * 10); + myPhaseShiftNtsc->setMaxValue((PaletteHandler::DEF_NTSC_SHIFT + PaletteHandler::MAX_SHIFT) * 10); myPhaseShiftNtsc->setTickmarkIntervals(4); wid.push_back(myPhaseShiftNtsc); ypos += lineHeight + VGAP; @@ -274,7 +285,8 @@ void VideoDialog::addPaletteTab() myPhaseShiftPal = new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight, "PAL phase", plWidth, kPalShiftChanged, fontWidth * 5); - myPhaseShiftPal->setMinValue(313 - 45); myPhaseShiftPal->setMaxValue(313 + 45); + myPhaseShiftPal->setMinValue((PaletteHandler::DEF_PAL_SHIFT - PaletteHandler::MAX_SHIFT) * 10); + myPhaseShiftPal->setMaxValue((PaletteHandler::DEF_PAL_SHIFT + PaletteHandler::MAX_SHIFT) * 10); myPhaseShiftPal->setTickmarkIntervals(4); wid.push_back(myPhaseShiftPal); ypos += lineHeight + VGAP; @@ -288,11 +300,15 @@ void VideoDialog::addPaletteTab() wid.push_back(myTV ## obj); \ ypos += lineHeight + VGAP; - CREATE_CUSTOM_SLIDERS(Hue, "Hue ", 0) - CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", 0) - CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", 0) - CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", 0) - CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", 0) + CREATE_CUSTOM_SLIDERS(Hue, "Hue ", kPaletteUpdated) + CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", kPaletteUpdated) + CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", kPaletteUpdated) + CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", kPaletteUpdated) + CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", kPaletteUpdated) + + // The resulting palette + addPalette(myPhaseShiftNtsc->getRight() + fontWidth * 2, VBORDER, + fontWidth * 2 * 8, myTVGamma->getBottom() - myTIAPalette->getTop()); // Add items for tab 2 addToFocusList(wid, myTab, tabID); @@ -412,13 +428,20 @@ void VideoDialog::loadConfig() myTIAZoom->setValue(instance().settings().getFloat("tia.zoom") * 100); // TIA Palette - myTIAPalette->setSelected( - instance().settings().getString("palette"), "standard"); + myPalette = instance().settings().getString("palette"); + myTIAPalette->setSelected(myPalette, "standard"); - // Custom Palette - myPhaseShiftNtsc->setValue(instance().settings().getFloat("tv.phase_ntsc") * 10); - myPhaseShiftPal->setValue(instance().settings().getFloat("tv.phase_pal") * 10); + // Palette adjustables + instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(myPaletteAdj); + myPhaseShiftNtsc->setValue(myPaletteAdj.phaseNtsc); + myPhaseShiftPal->setValue(myPaletteAdj.phasePal); + myTVHue->setValue(myPaletteAdj.hue); + myTVBright->setValue(myPaletteAdj.brightness); + myTVContrast->setValue(myPaletteAdj.contrast); + myTVSatur->setValue(myPaletteAdj.saturation); + myTVGamma->setValue(myPaletteAdj.gamma); handlePaletteChange(); + colorPalette(); // TIA interpolation myTIAInterpolate->setState(instance().settings().getBool("tia.inter")); @@ -459,15 +482,6 @@ void VideoDialog::loadConfig() int preset = instance().settings().getInt("tv.filter"); handleTVModeChange(NTSCFilter::Preset(preset)); - // Palette adjustables - PaletteHandler::Adjustable paletteAdj; - instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(paletteAdj); - myTVHue->setValue(paletteAdj.hue); - myTVBright->setValue(paletteAdj.brightness); - myTVContrast->setValue(paletteAdj.contrast); - myTVSatur->setValue(paletteAdj.saturation); - myTVGamma->setValue(paletteAdj.gamma); - // TV Custom adjustables loadTVAdjustables(NTSCFilter::Preset::CUSTOM); @@ -491,31 +505,12 @@ void VideoDialog::saveConfig() instance().settings().setValue("video", myRenderer->getSelectedTag().toString()); - // TIA zoom levels - instance().settings().setValue("tia.zoom", myTIAZoom->getValue() / 100.0); - - // TIA Palette - instance().settings().setValue("palette", - myTIAPalette->getSelectedTag().toString()); - - // Custom Palette - instance().settings().setValue("tv.phase_ntsc", myPhaseShiftNtsc->getValue() / 10.0); - instance().settings().setValue("tv.phase_pal", myPhaseShiftPal->getValue() / 10.0); - // TIA interpolation instance().settings().setValue("tia.inter", myTIAInterpolate->getState()); - // Aspect ratio setting (NTSC and PAL) - int oldAdjust = instance().settings().getInt("tia.vsizeadjust"); - int newAdjust = myVSizeAdjust->getValue(); - bool vsizeChanged = oldAdjust != newAdjust; - instance().settings().setValue("tia.vsizeadjust", newAdjust); + // Note: Palette values are saved directly when changed! - // Speed - int speedup = mySpeed->getValue(); - instance().settings().setValue("speed", unmapSpeed(speedup)); - if (instance().hasConsole()) instance().console().initializeAudio(); // Fullscreen instance().settings().setValue("fullscreen", myFullscreen->getState()); @@ -524,6 +519,22 @@ void VideoDialog::saveConfig() // Fullscreen overscan instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel()); + // TIA zoom levels + instance().settings().setValue("tia.zoom", myTIAZoom->getValue() / 100.0); + + // Aspect ratio setting (NTSC and PAL) + const int oldAdjust = instance().settings().getInt("tia.vsizeadjust"); + const int newAdjust = myVSizeAdjust->getValue(); + const bool vsizeChanged = oldAdjust != newAdjust; + + instance().settings().setValue("tia.vsizeadjust", newAdjust); + + // Speed + const int speedup = mySpeed->getValue(); + instance().settings().setValue("speed", unmapSpeed(speedup)); + if (instance().hasConsole()) + instance().console().initializeAudio(); + // Use sync to vertical blank instance().settings().setValue("vsync", myUseVSync->getState()); @@ -541,16 +552,6 @@ void VideoDialog::saveConfig() // TV Mode instance().settings().setValue("tv.filter", myTVMode->getSelectedTag().toString()); - - // Palette adjustables - PaletteHandler::Adjustable paletteAdj; - paletteAdj.hue = myTVHue->getValue(); - paletteAdj.saturation = myTVSatur->getValue(); - paletteAdj.contrast = myTVContrast->getValue(); - paletteAdj.brightness = myTVBright->getValue(); - paletteAdj.gamma = myTVGamma->getValue(); - instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(paletteAdj); - // TV Custom adjustables NTSCFilter::Adjustable ntscAdj; ntscAdj.sharpness = myTVSharp->getValue(); @@ -596,32 +597,36 @@ void VideoDialog::setDefaults() case 0: // General { myRenderer->setSelectedIndex(0); - myTIAZoom->setValue(300); myTIAInterpolate->setState(false); - myVSizeAdjust->setValue(0); - mySpeed->setValue(0); - + // screen size myFullscreen->setState(false); //myFullScreenMode->setSelectedIndex(0); myUseStretch->setState(false); + myTVOverscan->setValue(0); + myTIAZoom->setValue(300); + myVSizeAdjust->setValue(0); + // speed + mySpeed->setValue(0); myUseVSync->setState(true); + // misc myUIMessages->setState(true); myFastSCBios->setState(true); myUseThreads->setState(false); - handlePaletteChange(); + handleFullScreenChange(); break; } case 1: // Palettes myTIAPalette->setSelected("standard", ""); - myPhaseShiftNtsc->setValue(262); - myPhaseShiftPal->setValue(313); + myPhaseShiftNtsc->setValue(PaletteHandler::DEF_NTSC_SHIFT * 10); + myPhaseShiftPal->setValue(PaletteHandler::DEF_PAL_SHIFT * 10); myTVHue->setValue(50); myTVSatur->setValue(50); myTVContrast->setValue(50); myTVBright->setValue(50); myTVGamma->setValue(50); + handlePaletteChange(); break; case 2: // TV effects @@ -685,6 +690,27 @@ void VideoDialog::handlePaletteChange() myPhaseShiftPal->setEnabled(enable); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoDialog::handlePaletteUpdate() +{ + // TIA Palette + instance().settings().setValue("palette", + myTIAPalette->getSelectedTag().toString()); + // Palette adjustables + PaletteHandler::Adjustable paletteAdj; + paletteAdj.phaseNtsc = myPhaseShiftNtsc->getValue(); + paletteAdj.phasePal = myPhaseShiftPal->getValue(); + paletteAdj.hue = myTVHue->getValue(); + paletteAdj.saturation = myTVSatur->getValue(); + paletteAdj.contrast = myTVContrast->getValue(); + paletteAdj.brightness = myTVBright->getValue(); + paletteAdj.gamma = myTVGamma->getValue(); + instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(paletteAdj); + + if(instance().hasConsole()) + instance().frameBuffer().tiaSurface().paletteHandler().setPalette(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void VideoDialog::handleFullScreenChange() { @@ -722,12 +748,24 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd, close(); break; + case GuiObject::kCloseCmd: + // restore palette settings + instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(myPaletteAdj); + instance().frameBuffer().tiaSurface().paletteHandler().setPalette(myPalette); + Dialog::handleCommand(sender, cmd, data, 0); + break; + case GuiObject::kDefaultsCmd: setDefaults(); break; case kPaletteChanged: handlePaletteChange(); + handlePaletteUpdate(); + break; + + case kPaletteUpdated: + handlePaletteUpdate(); break; case kNtscShiftChanged: @@ -737,6 +775,7 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd, ss << std::setw(4) << std::fixed << std::setprecision(1) << (0.1 * abs(myPhaseShiftNtsc->getValue())) << DEGREE; myPhaseShiftNtsc->setValueLabel(ss.str()); + handlePaletteUpdate(); break; } case kPalShiftChanged: @@ -746,6 +785,7 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd, ss << std::setw(4) << std::fixed << std::setprecision(1) << (0.1 * abs(myPhaseShiftPal->getValue())) << DEGREE; myPhaseShiftPal->setValueLabel(ss.str()); + handlePaletteUpdate(); break; } case kVSizeChanged: @@ -818,3 +858,57 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd, break; } } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoDialog::addPalette(int x, int y, int w, int h) +{ + if(instance().hasConsole()) + { + constexpr int NUM_LUMA = 8; + constexpr int NUM_CHROMA = 16; + const GUI::Font& ifont = instance().frameBuffer().infoFont(); + const int lwidth = ifont.getMaxCharWidth() * 1.5; + const float COLW = float(w - lwidth) / NUM_LUMA; + const float COLH = float(h) / NUM_CHROMA; + const int yofs = (COLH - ifont.getFontHeight() + 1) / 2; + + for(int idx = 0; idx < NUM_CHROMA; ++idx) + { + myColorLbl[idx] = new StaticTextWidget(myTab, ifont, x, y + yofs + idx * COLH, " "); + for(int lum = 0; lum < NUM_LUMA; ++lum) + { + myColor[idx][lum] = new ColorWidget(myTab, _font, x + lwidth + lum * COLW, y + idx * COLH, + COLW + 1, COLH + 1, 0, false); + } + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoDialog::colorPalette() +{ + if(instance().hasConsole()) + { + constexpr int NUM_LUMA = 8; + constexpr int NUM_CHROMA = 16; + const int order[2][NUM_CHROMA] = + { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 4, 6, 8, 10, 12, 13, 11, 9, 7, 5, 3, 14, 15} + }; + const int type = instance().console().timing() == ConsoleTiming::pal ? 1 : 0; + + for(int idx = 0; idx < NUM_CHROMA; ++idx) + { + ostringstream ss; + const int color = order[type][idx]; + + ss << Common::Base::HEX1 << std::uppercase << color; + myColorLbl[idx]->setLabel(ss.str()); + for(int lum = 0; lum < NUM_LUMA; ++lum) + { + myColor[idx][lum]->setColor(color * NUM_CHROMA + lum * 2); // skip grayscale colors + } + } + } +} diff --git a/src/gui/VideoDialog.hxx b/src/gui/VideoDialog.hxx index d780a508f..7d01b6808 100644 --- a/src/gui/VideoDialog.hxx +++ b/src/gui/VideoDialog.hxx @@ -20,6 +20,7 @@ class CommandSender; class CheckboxWidget; +class ColorWidget; class DialogContainer; class PopUpWidget; class RadioButtonGroup; @@ -29,6 +30,7 @@ class TabWidget; class OSystem; #include "Dialog.hxx" +#include "PaletteHandler.hxx" #include "NTSCFilter.hxx" #include "bspf.hxx" @@ -50,10 +52,13 @@ class VideoDialog : public Dialog void handleTVModeChange(NTSCFilter::Preset); void loadTVAdjustables(NTSCFilter::Preset preset); void handlePaletteChange(); + void handlePaletteUpdate(); void handleFullScreenChange(); void handleOverscanChange(); void handlePhosphorChange(); void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + void addPalette(int x, int y, int h, int w); + void colorPalette(); private: TabWidget* myTab; @@ -77,6 +82,9 @@ class VideoDialog : public Dialog CheckboxWidget* myUIMessages{nullptr}; CheckboxWidget* myFastSCBios{nullptr}; CheckboxWidget* myUseThreads{nullptr}; + std::array myColorLbl{nullptr}; + //std::array myColor{nullptr}; + ColorWidget* myColor[16][8]{nullptr}; // TV effects adjustables (custom mode) PopUpWidget* myTVMode{nullptr}; @@ -106,10 +114,14 @@ class VideoDialog : public Dialog ButtonWidget* myCloneBad{nullptr}; ButtonWidget* myCloneCustom{nullptr}; + string myPalette; + PaletteHandler::Adjustable myPaletteAdj{0.0F}; + enum { kPaletteChanged = 'VDpl', kNtscShiftChanged = 'VDns', kPalShiftChanged = 'VDps', + kPaletteUpdated = 'VDpu', kSpeedupChanged = 'VDSp', kVSizeChanged = 'VDVs', kFullScreenChanged = 'VDFs', From 5686c37a5752c8b164f69932311455d2e73da4de Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 10 May 2020 21:53:02 +0200 Subject: [PATCH 06/14] add hue adjustment code to PaletteHandler --- src/common/PaletteHandler.cxx | 26 +++++++++++++++++++++++--- src/common/PaletteHandler.hxx | 3 ++- src/gui/VideoDialog.cxx | 28 ++++++++++------------------ 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/common/PaletteHandler.cxx b/src/common/PaletteHandler.cxx index e6bce1494..f6fed70cf 100644 --- a/src/common/PaletteHandler.cxx +++ b/src/common/PaletteHandler.cxx @@ -294,6 +294,7 @@ PaletteArray PaletteHandler::adjustPalette(const PaletteArray& palette) 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; @@ -313,10 +314,11 @@ PaletteArray PaletteHandler::adjustPalette(const PaletteArray& palette) int g = (pixel >> 8) & 0xff; int b = (pixel >> 0) & 0xff; - // TOOD: adjust hue (different for NTSC and PAL?) + // adjust hue (different for NTSC and PAL?) + adjustHue(r, g, b, hue); // adjust saturation - changeSaturation(r, g, b, saturation); + adustSaturation(r, g, b, saturation); // adjust contrast, brightness, gamma r = adjust[r]; @@ -496,7 +498,25 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PaletteHandler::changeSaturation(int& R, int& G, int& B, float change) +void PaletteHandler::adjustHue(int& R, int& G, int& B, float change) +{ + const float U = cos(-change * BSPF::PI_f); + const float W = sin(-change * BSPF::PI_f); + const float R_out = (.299 + .701 * U + .168 * W) * R + + (.587 - .587 * U + .330 * W) * G + + (.114 - .114 * U - .497 * W) * B; + const float G_out = (.299 - .299 * U - .328 * W) * R + + (.587 + .413 * U + .035 * W) * G + + (.114 - .114 * U + .292 * W) * B; + const float B_out = (.299 - .3 * U + 1.25 * W) * R + + (.587 - .588 * U - 1.05 * W) * G + + (.114 + .886 * U - .203 * W) * B; + + R = R_out; G = G_out; B = B_out; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::adustSaturation(int& R, int& G, int& B, float change) { // public-domain function by Darel Rex Finley // diff --git a/src/common/PaletteHandler.hxx b/src/common/PaletteHandler.hxx index 7c0f69dfc..ddb4bfaa1 100644 --- a/src/common/PaletteHandler.hxx +++ b/src/common/PaletteHandler.hxx @@ -110,7 +110,8 @@ class PaletteHandler PaletteArray adjustPalette(const PaletteArray& source); - void changeSaturation(int& R, int& G, int& B, float change); + void adjustHue(int& R, int& G, int& B, float change); + void adustSaturation(int& R, int& G, int& B, float change); /** Loads a user-defined palette file (from OSystem::paletteFile), filling the diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx index 41460d9ba..a90657892 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -76,6 +76,16 @@ namespace { } } +#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; + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) @@ -291,15 +301,6 @@ void VideoDialog::addPaletteTab() wid.push_back(myPhaseShiftPal); ypos += lineHeight + VGAP; -#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(Hue, "Hue ", kPaletteUpdated) CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", kPaletteUpdated) CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", kPaletteUpdated) @@ -349,15 +350,6 @@ void VideoDialog::addTVEffectsTab() const int swidth = myTVMode->getWidth() - INDENT - lwidth; xpos += INDENT; -#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(Sharp, "Sharpness ", 0) CREATE_CUSTOM_SLIDERS(Res, "Resolution ", 0) CREATE_CUSTOM_SLIDERS(Artifacts, "Artifacts ", 0) From 5aa57decb5012a98e4c50289921e3d97e72aa997 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sun, 10 May 2020 22:53:58 +0200 Subject: [PATCH 07/14] some transformation code cleanup --- src/common/PaletteHandler.cxx | 68 +++++++++++------------------------ src/common/PaletteHandler.hxx | 3 +- 2 files changed, 21 insertions(+), 50 deletions(-) diff --git a/src/common/PaletteHandler.cxx b/src/common/PaletteHandler.cxx index f6fed70cf..dbca46ff2 100644 --- a/src/common/PaletteHandler.cxx +++ b/src/common/PaletteHandler.cxx @@ -314,11 +314,8 @@ PaletteArray PaletteHandler::adjustPalette(const PaletteArray& palette) int g = (pixel >> 8) & 0xff; int b = (pixel >> 0) & 0xff; - // adjust hue (different for NTSC and PAL?) - adjustHue(r, g, b, hue); - - // adjust saturation - adustSaturation(r, g, b, saturation); + // adjust hue (different for NTSC and PAL?) and saturation + adjustHueSaturation(r, g, b, hue, saturation); // adjust contrast, brightness, gamma r = adjust[r]; @@ -498,51 +495,26 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PaletteHandler::adjustHue(int& R, int& G, int& B, float change) +void PaletteHandler::adjustHueSaturation(int& R, int& G, int& B, float H, float S) { - const float U = cos(-change * BSPF::PI_f); - const float W = sin(-change * BSPF::PI_f); - const float R_out = (.299 + .701 * U + .168 * W) * R - + (.587 - .587 * U + .330 * W) * G - + (.114 - .114 * U - .497 * W) * B; - const float G_out = (.299 - .299 * U - .328 * W) * R - + (.587 + .413 * U + .035 * W) * G - + (.114 - .114 * U + .292 * W) * B; - const float B_out = (.299 - .3 * U + 1.25 * W) * R - + (.587 - .588 * U - 1.05 * W) * G - + (.114 + .886 * U - .203 * W) * B; + // Adapted from http://beesbuzz.biz/code/16-hsv-color-transforms + // (C) J. “Fluffy” Shagam + // License: CC BY-SA 4.0 + const float su = S * cos(-H * BSPF::PI_f); + const float sw = S * sin(-H * BSPF::PI_f); + const float r = (.299 + .701 * su + .168 * sw) * R + + (.587 - .587 * su + .330 * sw) * G + + (.114 - .114 * su - .497 * sw) * B; + const float g = (.299 - .299 * su - .328 * sw) * R + + (.587 + .413 * su + .035 * sw) * G + + (.114 - .114 * su + .292 * sw) * B; + const float b = (.299 - .300 * su + 1.25 * sw) * R + + (.587 - .588 * su - 1.05 * sw) * G + + (.114 + .886 * su - .203 * sw) * B; - R = R_out; G = G_out; B = B_out; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PaletteHandler::adustSaturation(int& R, int& G, int& B, float change) -{ - // public-domain function by Darel Rex Finley - // - // The passed-in RGB values can be on any desired scale, such as 0 to - // to 1, or 0 to 255. (But use the same scale for all three!) - // - // The "change" parameter works like this: - // 0.0 creates a black-and-white image. - // 0.5 reduces the color saturation by half. - // 1.0 causes no change. - // 2.0 doubles the color saturation. - // Note: A "change" value greater than 1.0 may project your RGB values - // beyond their normal range, in which case you probably should truncate - // them to the desired range before trying to use them in an image. - constexpr float PR = .2989F; - constexpr float PG = .5870F; - constexpr float PB = .1140F; - const float P = sqrt(R * R * PR + G * G * PG + B * B * PB) ; - - R = P + (R - P) * change; - G = P + (G - P) * change; - B = P + (B - P) * change; - - R = BSPF::clamp(R, 0, 255); - G = BSPF::clamp(G, 0, 255); - B = BSPF::clamp(B, 0, 255); + R = BSPF::clamp(r, 0.F, 255.F); + G = BSPF::clamp(g, 0.F, 255.F); + B = BSPF::clamp(b, 0.F, 255.F); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/PaletteHandler.hxx b/src/common/PaletteHandler.hxx index ddb4bfaa1..cffdc2ad4 100644 --- a/src/common/PaletteHandler.hxx +++ b/src/common/PaletteHandler.hxx @@ -110,8 +110,7 @@ class PaletteHandler PaletteArray adjustPalette(const PaletteArray& source); - void adjustHue(int& R, int& G, int& B, float change); - void adustSaturation(int& R, int& G, int& B, float change); + void adjustHueSaturation(int& R, int& G, int& B, float H, float S); /** Loads a user-defined palette file (from OSystem::paletteFile), filling the From 614e28375de435f4d6a236dd9b7142feaf70b215 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Mon, 11 May 2020 10:47:43 +0200 Subject: [PATCH 08/14] code cleanup and bug fixing --- src/common/PKeyboardHandler.cxx | 2 - src/common/PaletteHandler.cxx | 150 ++++++++++++--------------- src/common/PaletteHandler.hxx | 122 ++++++++++++++++------ src/common/tv_filters/NTSCFilter.cxx | 26 ++--- src/emucore/Event.hxx | 1 - src/emucore/EventHandler.cxx | 19 +--- src/emucore/EventHandler.hxx | 2 +- src/emucore/Settings.cxx | 10 +- src/gui/CommandDialog.cxx | 8 +- src/gui/VideoDialog.cxx | 12 +-- 10 files changed, 193 insertions(+), 159 deletions(-) diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx index 1a0fe6499..3edd7698d 100644 --- a/src/common/PKeyboardHandler.cxx +++ b/src/common/PKeyboardHandler.cxx @@ -491,8 +491,6 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo {Event::ToggleColorLoss, KBDK_L, KBDM_CTRL}, {Event::PaletteDecrease, KBDK_P, KBDM_SHIFT | KBDM_CTRL}, {Event::PaletteIncrease, KBDK_P, KBDM_CTRL}, - {Event::ColorShiftDecrease, KBDK_9, KBDM_SHIFT | KBDM_CTRL}, - {Event::ColorShiftIncrease, KBDK_9, 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 index dbca46ff2..3f1066724 100644 --- a/src/common/PaletteHandler.cxx +++ b/src/common/PaletteHandler.cxx @@ -54,19 +54,14 @@ string PaletteHandler::toPaletteName(PaletteType type) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PaletteHandler::changePalette(bool increase) +void PaletteHandler::cyclePalette(bool next) { const string MESSAGES[PaletteType::NumTypes] = { "Standard Stella", "Z26", "User-defined", "Custom" }; - - string palette, message; - palette = myOSystem.settings().getString("palette"); - - int type = toPaletteType(myOSystem.settings().getString("palette")); - if(increase) + if(next) { if(type == PaletteType::MaxType) type = PaletteType::Standard; @@ -87,8 +82,8 @@ void PaletteHandler::changePalette(bool increase) type--; } - palette = toPaletteName(PaletteType(type)); - message = MESSAGES[type] + " palette"; + const string palette = toPaletteName(PaletteType(type)); + const string message = MESSAGES[type] + " palette"; myOSystem.frameBuffer().showMessage(message); @@ -96,9 +91,10 @@ void PaletteHandler::changePalette(bool increase) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PaletteHandler::selectAdjustable(bool next) +void PaletteHandler::cycleAdjustable(bool next) { - const bool isCustomPalette = "custom" == myOSystem.settings().getString("palette"); + const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette"); + bool isPhaseShift; do { if(next) @@ -113,11 +109,19 @@ void PaletteHandler::selectAdjustable(bool next) else myCurrentAdjustable--; } - } while(!isCustomPalette && myAdjustables[myCurrentAdjustable].value == nullptr); + isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr; + + // skip phase shift when 'Custom' palette is not selected + } while(isPhaseShift && !isCustomPalette); ostringstream buf; - buf << "Palette adjustable '" << myAdjustables[myCurrentAdjustable].type - << "' selected"; + 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()); } @@ -129,25 +133,19 @@ void PaletteHandler::changeAdjustable(bool increase) changeColorPhaseShift(increase); else { - float newVal = (*myAdjustables[myCurrentAdjustable].value); + int newVal = scaleTo100(*myAdjustables[myCurrentAdjustable].value); if(increase) - { - newVal += 0.05F; - if(newVal > 1.0F) - newVal = 1.0F; - } + newVal += 2; // += 2% else - { - newVal -= 0.05F; - if(newVal < -1.0F) - newVal = -1.0F; - } - *myAdjustables[myCurrentAdjustable].value = newVal; + newVal -= 2; // -= 2% + newVal = BSPF::clamp(newVal, 0, 100); + + *myAdjustables[myCurrentAdjustable].value = scaleFrom100(newVal); ostringstream buf; - buf << "Custom '" << myAdjustables[myCurrentAdjustable].type - << "' set to " << int((newVal + 1.0F) * 100.0F + 0.5F) << "%"; + buf << "Custom '" << myAdjustables[myCurrentAdjustable].name + << "' set to " << newVal << "%"; myOSystem.frameBuffer().showMessage(buf.str()); setPalette(); @@ -162,32 +160,27 @@ void PaletteHandler::changeColorPhaseShift(bool increase) // SECAM is not supported if(timing != ConsoleTiming::secam) { - constexpr char DEGREE = 0x1c; const bool isNTSC = timing == ConsoleTiming::ntsc; const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT; - float phase = isNTSC ? myPhaseNTSC : myPhasePAL; + float newPhase = isNTSC ? myPhaseNTSC : myPhasePAL; if(increase) // increase color phase shift - { - phase += 0.3F; - phase = std::min(phase, shift + MAX_SHIFT); - } + newPhase += 0.3F; else // decrease color phase shift - { - phase -= 0.3F; - phase = std::max(phase, shift - MAX_SHIFT); - } + newPhase -= 0.3F; + newPhase = BSPF::clamp(newPhase, shift - MAX_SHIFT, shift + MAX_SHIFT); + if(isNTSC) - myPhaseNTSC = phase; + myPhaseNTSC = newPhase; else - myPhasePAL = phase; + myPhasePAL = newPhase; generateCustomPalette(timing); - setPalette("custom"); + setPalette(SETTING_CUSTOM); ostringstream ss; ss << "Color phase shift at " - << std::fixed << std::setprecision(1) << phase << DEGREE; + << std::fixed << std::setprecision(1) << newPhase << DEGREE; myOSystem.frameBuffer().showMessage(ss.str()); } @@ -260,30 +253,33 @@ void PaletteHandler::setPalette(const string& name) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PaletteHandler::setPalette() { - const string& name = myOSystem.settings().getString("palette"); + 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)]; + // 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); + if(paletteType == PaletteType::Custom) + generateCustomPalette(timing); - myOSystem.frameBuffer().setTIAPalette(adjustPalette(*palette)); + myOSystem.frameBuffer().setTIAPalette(adjustedPalette(*palette)); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray PaletteHandler::adjustPalette(const PaletteArray& palette) +PaletteArray PaletteHandler::adjustedPalette(const PaletteArray& palette) { PaletteArray destPalette; // Constants for saturation and gray scale calculation @@ -387,15 +383,15 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) { constexpr int NUM_CHROMA = 16; constexpr int NUM_LUMA = 8; - constexpr float SATURATION = 0.25F; + 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 * (2 * BSPF::PI_f / 360); - const float shift = myPhaseNTSC * (2 * BSPF::PI_f / 360); + 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++) @@ -425,13 +421,9 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) 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; + 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; } @@ -439,9 +431,9 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) } else if(timing == ConsoleTiming::pal) { - constexpr float offset = 180 * (2 * BSPF::PI_f / 360); - const float shift = myPhasePAL * (2 * BSPF::PI_f / 360); - constexpr float fixedShift = 22.5F * (2 * BSPF::PI_f / 360); + 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++) @@ -470,7 +462,7 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) // 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; + //float G = 1.704 * Y - 0.590 * R - 0.194 * B; if(R < 0) R = 0.0; if(G < 0) G = 0.0; @@ -480,13 +472,9 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) G = powf(G, 1.2F); B = powf(B, 1.2F); - 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; + 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; } diff --git a/src/common/PaletteHandler.hxx b/src/common/PaletteHandler.hxx index cffdc2ad4..237d9b878 100644 --- a/src/common/PaletteHandler.hxx +++ b/src/common/PaletteHandler.hxx @@ -25,22 +25,18 @@ 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 DEF_PAL_SHIFT = 31.3F; // ~= 360 / 11.5 static constexpr float MAX_SHIFT = 4.5F; - enum DisplayType { - NTSC, - PAL, - SECAM, - NumDisplayTypes - }; - + // Externally used adjustment parameters struct Adjustable { float phaseNtsc, phasePal; uInt32 hue, saturation, contrast, brightness, gamma; @@ -51,28 +47,38 @@ class PaletteHandler virtual ~PaletteHandler() = default; /** - Switch between the available palettes. - */ - void changePalette(bool increase = true); + Cycle through available palettes. - void selectAdjustable(bool next = true); + @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; - /** - 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); - /** Sets the palette according to the given palette name. @@ -80,18 +86,14 @@ class PaletteHandler */ void setPalette(const string& name); - /** Sets the palette from current settings. */ void setPalette(); - /** - Generates a custom palette, based on user defined phase shifts. - */ - void generateCustomPalette(ConsoleTiming timing); - private: + static constexpr char DEGREE = 0x1c; + enum PaletteType { Standard, Z26, @@ -102,14 +104,64 @@ class PaletteHandler MaxType = Custom }; + /** + Convert adjustables from/to 100% scale + */ float scaleFrom100(float x) const { return (x / 50.F) - 1.F; } 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; - PaletteArray adjustPalette(const PaletteArray& source); + /** + 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 type 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); /** @@ -118,15 +170,16 @@ class PaletteHandler */ void loadUserPalette(); - private: static constexpr int NUM_ADJUSTABLES = 6; OSystem& myOSystem; + // The currently selected adjustable uInt32 myCurrentAdjustable{0}; + struct AdjustableTag { - const char* const type{nullptr}; + const char* const name{nullptr}; float* value{nullptr}; }; const std::array myAdjustables = @@ -139,8 +192,9 @@ class PaletteHandler { "gamma", &myGamma }, } }; - float myPhaseNTSC{0.0F}; - float myPhasePAL{0.0F}; + // 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 @@ -169,7 +223,7 @@ class PaletteHandler static PaletteArray ourUserPALPalette; static PaletteArray ourUserSECAMPalette; - // Table of RGB values for NTSC, PAL - custom-defined + // Table of RGB values for NTSC, PAL - custom-defined and generated static PaletteArray ourCustomNTSCPalette; static PaletteArray ourCustomPALPalette; diff --git a/src/common/tv_filters/NTSCFilter.cxx b/src/common/tv_filters/NTSCFilter.cxx index 8a40ddd2c..64f26da2b 100644 --- a/src/common/tv_filters/NTSCFilter.cxx +++ b/src/common/tv_filters/NTSCFilter.cxx @@ -74,8 +74,8 @@ 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; @@ -85,7 +85,8 @@ string NTSCFilter::setNextAdjustable() ostringstream buf; buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type - << "' selected"; + << "' selected (" + << scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value) << "%)"; return buf.str(); } @@ -93,8 +94,8 @@ 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; @@ -104,7 +105,8 @@ string NTSCFilter::setPreviousAdjustable() else --myCurrentAdjustable; ostringstream buf; buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type - << "' selected"; + << "' selected (" + << scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value) << "%)"; return buf.str(); } @@ -112,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; @@ -121,7 +123,7 @@ string NTSCFilter::increaseAdjustable() ostringstream buf; buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type - << "' set to " << newval; + << "' set to " << newval << "%"; setPreset(myPreset); return buf.str(); @@ -130,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; @@ -140,7 +142,7 @@ string NTSCFilter::decreaseAdjustable() ostringstream buf; buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type - << "' set to " << newval; + << "' set to " << newval << "%"; setPreset(myPreset); return buf.str(); diff --git a/src/emucore/Event.hxx b/src/emucore/Event.hxx index ae82ef810..fba15b6fb 100644 --- a/src/emucore/Event.hxx +++ b/src/emucore/Event.hxx @@ -101,7 +101,6 @@ class Event RewindPause, UnwindPause, FormatDecrease, FormatIncrease, PaletteDecrease, PaletteIncrease, ToggleColorLoss, - ColorShiftDecrease, ColorShiftIncrease, PreviousPaletteAttribute, NextPaletteAttribute, PaletteAttributeDecrease, PaletteAttributeIncrease, ToggleFullScreen, VidmodeDecrease, VidmodeIncrease, diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index 325438765..362625909 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -437,11 +437,11 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) return; case Event::PreviousPaletteAttribute: - if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().selectAdjustable(false); + if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(false); return; case Event::NextPaletteAttribute: - if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().selectAdjustable(true); + if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(true); return; case Event::PaletteAttributeDecrease: @@ -452,14 +452,6 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().changeAdjustable(true); return; - case Event::ColorShiftDecrease: - if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().changeColorPhaseShift(false); - return; - - case Event::ColorShiftIncrease: - if (pressed) myOSystem.frameBuffer().tiaSurface().paletteHandler().changeColorPhaseShift(true); - return; - case Event::ToggleFullScreen: if (pressed && !repeated) myOSystem.frameBuffer().toggleFullscreen(); return; @@ -565,11 +557,11 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) return; case Event::PaletteDecrease: - if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().paletteHandler().changePalette(false); + if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(false); return; case Event::PaletteIncrease: - if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().paletteHandler().changePalette(true); + if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(true); return; case Event::ToggleInter: @@ -1965,8 +1957,6 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { { { Event::NextPaletteAttribute, "Select next palette attribute", "" }, { Event::PaletteAttributeDecrease,"Decrease selected palette attribute", "" }, { Event::PaletteAttributeIncrease,"Increase selected palette attribute", "" }, - { Event::ColorShiftDecrease, "Decrease custom palette phase shift", "" }, - { Event::ColorShiftIncrease, "Increase custom palette phase shift", "" }, { Event::ToggleInter, "Toggle display interpolation", "" }, // Blargg TV effects: { Event::VidmodeStd, "Disable TV effects", "" }, @@ -2097,7 +2087,6 @@ const Event::EventSet EventHandler::AudioVideoEvents = { Event::ScanlineAdjustDecrease, Event::ScanlineAdjustIncrease, Event::OverscanDecrease, Event::OverscanIncrease, Event::PaletteDecrease, Event::PaletteIncrease, - Event::ColorShiftDecrease, Event::ColorShiftIncrease, Event::PreviousVideoMode, Event::NextVideoMode, Event::PreviousPaletteAttribute, Event::NextPaletteAttribute, Event::PaletteAttributeDecrease, Event::PaletteAttributeIncrease, diff --git a/src/emucore/EventHandler.hxx b/src/emucore/EventHandler.hxx index fd8522e5f..6d19b685b 100644 --- a/src/emucore/EventHandler.hxx +++ b/src/emucore/EventHandler.hxx @@ -468,7 +468,7 @@ class EventHandler #else PNG_SIZE = 0, #endif - EMUL_ACTIONLIST_SIZE = 154 + PNG_SIZE + COMBO_SIZE, + EMUL_ACTIONLIST_SIZE = 152 + PNG_SIZE + COMBO_SIZE, MENU_ACTIONLIST_SIZE = 18 ; diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index a959cc255..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,7 +46,7 @@ Settings::Settings() setPermanent("center", "true"); setPermanent("windowedpos", Common::Point(50, 50)); setPermanent("display", 0); - setPermanent("palette", "standard"); + setPermanent("palette", PaletteHandler::SETTING_STANDARD); setPermanent("uimessages", "true"); // TIA specific options @@ -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/gui/CommandDialog.cxx b/src/gui/CommandDialog.cxx index 0d8729635..5790f7193 100644 --- a/src/gui/CommandDialog.cxx +++ b/src/gui/CommandDialog.cxx @@ -204,7 +204,7 @@ void CommandDialog::handleCommand(CommandSender* sender, int cmd, break; case kPaletteCmd: - instance().frameBuffer().tiaSurface().paletteHandler().changePalette(); + instance().frameBuffer().tiaSurface().paletteHandler().cyclePalette(); updatePalette(); break; @@ -270,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/VideoDialog.cxx b/src/gui/VideoDialog.cxx index a90657892..bc1fdfa36 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -269,11 +269,11 @@ void VideoDialog::addPaletteTab() // TIA Palette items.clear(); - VarList::push_back(items, "Standard", "standard"); - VarList::push_back(items, "z26", "z26"); + VarList::push_back(items, "Standard", PaletteHandler::SETTING_STANDARD); + VarList::push_back(items, "z26", PaletteHandler::SETTING_Z26); if (instance().checkUserPalette()) - VarList::push_back(items, "User", "user"); - VarList::push_back(items, "Custom", "custom"); + 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); @@ -421,7 +421,7 @@ void VideoDialog::loadConfig() // TIA Palette myPalette = instance().settings().getString("palette"); - myTIAPalette->setSelected(myPalette, "standard"); + myTIAPalette->setSelected(myPalette, PaletteHandler::SETTING_STANDARD); // Palette adjustables instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(myPaletteAdj); @@ -610,7 +610,7 @@ void VideoDialog::setDefaults() } case 1: // Palettes - myTIAPalette->setSelected("standard", ""); + myTIAPalette->setSelected(PaletteHandler::SETTING_STANDARD); myPhaseShiftNtsc->setValue(PaletteHandler::DEF_NTSC_SHIFT * 10); myPhaseShiftPal->setValue(PaletteHandler::DEF_PAL_SHIFT * 10); myTVHue->setValue(50); From 259c0bf48fe0d0539d56ccc220a14e31bb123f1c Mon Sep 17 00:00:00 2001 From: thrust26 Date: Mon, 11 May 2020 16:15:12 +0200 Subject: [PATCH 09/14] refactored Video and Audio dialogs into common dialog created new EmulationDialog (re)moved some includes to reduce compile time --- src/debugger/gui/CartDebugWidget.hxx | 3 - src/debugger/gui/CartEnhancedWidget.cxx | 2 + src/debugger/gui/DebuggerDialog.hxx | 2 +- src/emucore/OSystem.hxx | 2 +- src/gui/AudioDialog.cxx | 353 ------------ src/gui/AudioDialog.hxx | 77 --- src/gui/DeveloperDialog.cxx | 42 -- src/gui/DeveloperDialog.hxx | 2 - src/gui/EmulationDialog.cxx | 283 ++++++++++ src/gui/EmulationDialog.hxx | 63 +++ src/gui/InputDialog.cxx | 2 +- src/gui/OptionsDialog.cxx | 26 +- src/gui/OptionsDialog.hxx | 10 +- src/gui/UIDialog.cxx | 14 +- src/gui/UIDialog.hxx | 1 - .../{VideoDialog.cxx => VideoAudioDialog.cxx} | 528 ++++++++++++------ .../{VideoDialog.hxx => VideoAudioDialog.hxx} | 89 +-- src/gui/module.mk | 4 +- src/libpng/pngconf.h | 6 +- src/windows/Stella.vcxproj | 8 +- src/windows/Stella.vcxproj.filters | 24 +- 21 files changed, 795 insertions(+), 746 deletions(-) delete mode 100644 src/gui/AudioDialog.cxx delete mode 100644 src/gui/AudioDialog.hxx create mode 100644 src/gui/EmulationDialog.cxx create mode 100644 src/gui/EmulationDialog.hxx rename src/gui/{VideoDialog.cxx => VideoAudioDialog.cxx} (66%) rename src/gui/{VideoDialog.hxx => VideoAudioDialog.hxx} (75%) 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/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.hxx b/src/debugger/gui/DebuggerDialog.hxx index b66ae37a6..bfd7c332b 100644 --- a/src/debugger/gui/DebuggerDialog.hxx +++ b/src/debugger/gui/DebuggerDialog.hxx @@ -33,6 +33,7 @@ class TiaOutputWidget; class TiaZoomWidget; class CartDebugWidget; class CartRamWidget; +class OptionsDialog; namespace Common { struct Rect; @@ -40,7 +41,6 @@ namespace Common { #include "Dialog.hxx" #include "MessageBox.hxx" -#include "OptionsDialog.hxx" class DebuggerDialog : public Dialog { 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/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/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/EmulationDialog.cxx b/src/gui/EmulationDialog.cxx new file mode 100644 index 000000000..111fa12f9 --- /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; + } +} \ No newline at end of file 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/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 94032a4ce..eafc2e00b 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -127,13 +127,8 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, myCenter = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Center windows"); wid.push_back(myCenter); - // Confirm dialog when exiting emulation - xpos = HBORDER; ypos += lineHeight + VGAP * 2; - myConfirmExitWidget = new CheckboxWidget(myTab, font, xpos, ypos, "Confirm exiting emulation"); - wid.push_back(myConfirmExitWidget); - ypos += lineHeight + VGAP * 3; - // 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, @@ -384,9 +379,6 @@ void UIDialog::loadConfig() // Center window myCenter->setState(settings.getBool("center")); - // Confirm dialog when exiting emulation - myConfirmExitWidget->setState(settings.getBool("confirmexit")); - // Listwidget quick delay int delay = settings.getInt("listdelay"); myListDelaySlider->setValue(delay); @@ -462,9 +454,6 @@ void UIDialog::saveConfig() // Center window settings.setValue("center", myCenter->getState()); - // Confirm dialog when exiting emulation - settings.setValue("confirmexit", myConfirmExitWidget->getState()); - // Listwidget quick delay settings.setValue("listdelay", myListDelaySlider->getValue()); FileListWidget::setQuickSelectDelay(myListDelaySlider->getValue()); @@ -501,7 +490,6 @@ void UIDialog::setDefaults() myHidpiWidget->setState(false); myPositionPopup->setSelected("0"); myCenter->setState(false); - myConfirmExitWidget->setState(false); myListDelaySlider->setValue(300); myWheelLinesSlider->setValue(4); myDoubleClickSlider->setValue(500); diff --git a/src/gui/UIDialog.hxx b/src/gui/UIDialog.hxx index 91bc7ff82..6ed1c655f 100644 --- a/src/gui/UIDialog.hxx +++ b/src/gui/UIDialog.hxx @@ -70,7 +70,6 @@ class UIDialog : public Dialog, public CommandSender CheckboxWidget* myHidpiWidget{nullptr}; PopUpWidget* myPositionPopup{nullptr}; CheckboxWidget* myCenter{nullptr}; - CheckboxWidget* myConfirmExitWidget{nullptr}; SliderWidget* myListDelaySlider{nullptr}; SliderWidget* myWheelLinesSlider{nullptr}; SliderWidget* myControllerRateSlider{nullptr}; diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoAudioDialog.cxx similarity index 66% rename from src/gui/VideoDialog.cxx rename to src/gui/VideoAudioDialog.cxx index bc1fdfa36..dbab74acf 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoAudioDialog.cxx @@ -20,6 +20,8 @@ #include "bspf.hxx" #include "Base.hxx" #include "Control.hxx" +#include "Cart.hxx" +#include "CartDPC.hxx" #include "Dialog.hxx" #include "Menu.hxx" #include "OSystem.hxx" @@ -30,51 +32,15 @@ #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 "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(); - } -} +#include "VideoAudioDialog.hxx" #define CREATE_CUSTOM_SLIDERS(obj, desc, cmd) \ myTV ## obj = \ @@ -87,9 +53,9 @@ namespace { ypos += lineHeight + VGAP; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, +VideoAudioDialog::VideoAudioDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) - : Dialog(osystem, parent, font, "Video settings") + : Dialog(osystem, parent, font, "Video & Audio settings") { const int lineHeight = _font.getLineHeight(), fontHeight = _font.getFontHeight(), @@ -101,8 +67,8 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, int xpos, ypos; // Set real dimensions - setSize(57 * fontWidth + HBORDER * 2 + PopUpWidget::dropDownWidth(font) * 2, - _th + VGAP * 3 + lineHeight + 11 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3, + 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 @@ -112,9 +78,10 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, _h - _th - VGAP - buttonHeight - VBORDER * 2); addTabWidget(myTab); - addGeneralTab(); + addDisplayTab(); addPaletteTab(); addTVEffectsTab(); + addAudioTab(); //const int req_w = std::max(myFastSCBios->getRight(), myCloneBad->getRight()) + HBORDER + 1; //const int req_h = _th + VGAP * 3 @@ -141,7 +108,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::addGeneralTab() +void VideoAudioDialog::addDisplayTab() { const int lineHeight = _font.getLineHeight(), fontHeight = _font.getFontHeight(), @@ -152,24 +119,32 @@ void VideoDialog::addGeneralTab() const int HBORDER = fontWidth * 1.25; const int INDENT = CheckboxWidget::prefixSize(_font); const int lwidth = _font.getStringWidth("V-Size adjust "), - pwidth = _font.getStringWidth("XXXXxXXXX"); + pwidth = _font.getStringWidth("OpenGLES2"); int xpos = HBORDER, ypos = VBORDER; WidgetArray wid; VariantList items; - const int tabID = myTab->addTab(" General "); + 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); @@ -187,7 +162,6 @@ void VideoDialog::addGeneralTab() ypos += lineHeight + VGAP; // FS overscan - const int swidth = myRenderer->getWidth() - lwidth; myTVOverscan = new SliderWidget(myTab, _font, xpos + INDENT, ypos - 1, swidth, lineHeight, "Overscan", lwidth - INDENT, kOverscanChanged, fontWidth * 3, "%"); myTVOverscan->setMinValue(0); myTVOverscan->setMaxValue(10); @@ -195,13 +169,6 @@ void VideoDialog::addGeneralTab() wid.push_back(myTVOverscan); 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; - // Vertical size myVSizeAdjust = new SliderWidget(myTab, _font, xpos, ypos-1, swidth, lineHeight, @@ -209,47 +176,13 @@ void VideoDialog::addGeneralTab() myVSizeAdjust->setMinValue(-5); myVSizeAdjust->setMaxValue(5); myVSizeAdjust->setTickmarkIntervals(2); wid.push_back(myVSizeAdjust); - ypos += lineHeight + VGAP * 4; - - // 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; - - // 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; - - // 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); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::addPaletteTab() +void VideoAudioDialog::addPaletteTab() { const int lineHeight = _font.getLineHeight(), fontHeight = _font.getFontHeight(), @@ -265,7 +198,7 @@ void VideoDialog::addPaletteTab() ypos = VBORDER; WidgetArray wid; VariantList items; - const int tabID = myTab->addTab(" Palettes "); + const int tabID = myTab->addTab(" Palettes ", TabWidget::AUTO_WIDTH); // TIA Palette items.clear(); @@ -308,15 +241,16 @@ void VideoDialog::addPaletteTab() CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", kPaletteUpdated) // The resulting palette - addPalette(myPhaseShiftNtsc->getRight() + fontWidth * 2, VBORDER, - fontWidth * 2 * 8, myTVGamma->getBottom() - myTIAPalette->getTop()); + 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 VideoDialog::addTVEffectsTab() +void VideoAudioDialog::addTVEffectsTab() { const int lineHeight = _font.getLineHeight(), fontHeight = _font.getFontHeight(), @@ -332,7 +266,7 @@ void VideoDialog::addTVEffectsTab() const int pwidth = _font.getStringWidth("Bad adjust "); WidgetArray wid; VariantList items; - const int tabID = myTab->addTab(" TV Effects "); + const int tabID = myTab->addTab(" TV Effects ", TabWidget::AUTO_WIDTH); items.clear(); VarList::push_back(items, "Disabled", static_cast(NTSCFilter::Preset::OFF)); @@ -403,11 +337,138 @@ void VideoDialog::addTVEffectsTab() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::loadConfig() +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 @@ -419,6 +480,21 @@ void VideoDialog::loadConfig() 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); @@ -435,39 +511,8 @@ void VideoDialog::loadConfig() handlePaletteChange(); colorPalette(); - // 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")); - - // Fast loading of Supercharger BIOS - myFastSCBios->setState(instance().settings().getBool("fastscbios")); - - // Multi-threaded rendering - myUseThreads->setState(instance().settings().getBool("threads")); - + ///////////////////////////////////////////////////////////////////////////// + // TV Effects tab // TV Mode myTVMode->setSelected( instance().settings().getString("tv.filter"), "0"); @@ -487,12 +532,60 @@ void VideoDialog::loadConfig() // TV scanline intensity and interpolation myTVScanIntense->setValue(instance().settings().getInt("tv.scanlines")); + ///////////////////////////////////////////////////////////////////////////// + // Audio tab + AudioSettings& audioSettings = instance().audioSettings(); + + // Enable sound +#ifndef 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 VideoDialog::saveConfig() +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()); @@ -500,10 +593,6 @@ void VideoDialog::saveConfig() // TIA interpolation instance().settings().setValue("tia.inter", myTIAInterpolate->getState()); - - // Note: Palette values are saved directly when changed! - - // Fullscreen instance().settings().setValue("fullscreen", myFullscreen->getState()); // Fullscreen stretch setting @@ -521,26 +610,12 @@ void VideoDialog::saveConfig() instance().settings().setValue("tia.vsizeadjust", newAdjust); - // Speed - const int speedup = mySpeed->getValue(); - instance().settings().setValue("speed", unmapSpeed(speedup)); - if (instance().hasConsole()) - instance().console().initializeAudio(); - // Use sync to vertical blank - instance().settings().setValue("vsync", myUseVSync->getState()); + // Note: Palette values are saved directly when changed! - // Show UI messages - instance().settings().setValue("uimessages", myUIMessages->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 Effects tab // TV Mode instance().settings().setValue("tv.filter", myTVMode->getSelectedTag().toString()); @@ -579,10 +654,51 @@ void VideoDialog::saveConfig() // ... 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 VideoDialog::setDefaults() +void VideoAudioDialog::setDefaults() { switch(myTab->getActiveTab()) { @@ -597,13 +713,6 @@ void VideoDialog::setDefaults() myTVOverscan->setValue(0); myTIAZoom->setValue(300); myVSizeAdjust->setValue(0); - // speed - mySpeed->setValue(0); - myUseVSync->setState(true); - // misc - myUIMessages->setState(true); - myFastSCBios->setState(true); - myUseThreads->setState(false); handleFullScreenChange(); break; @@ -640,11 +749,29 @@ void VideoDialog::setDefaults() 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 VideoDialog::handleTVModeChange(NTSCFilter::Preset preset) +void VideoAudioDialog::handleTVModeChange(NTSCFilter::Preset preset) { bool enable = preset == NTSCFilter::Preset::CUSTOM; @@ -661,7 +788,7 @@ void VideoDialog::handleTVModeChange(NTSCFilter::Preset preset) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::loadTVAdjustables(NTSCFilter::Preset preset) +void VideoAudioDialog::loadTVAdjustables(NTSCFilter::Preset preset) { NTSCFilter::Adjustable adj; instance().frameBuffer().tiaSurface().ntsc().getAdjustables( @@ -674,7 +801,7 @@ void VideoDialog::loadTVAdjustables(NTSCFilter::Preset preset) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handlePaletteChange() +void VideoAudioDialog::handlePaletteChange() { bool enable = myTIAPalette->getSelectedTag().toString() == "custom"; @@ -683,7 +810,7 @@ void VideoDialog::handlePaletteChange() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handlePaletteUpdate() +void VideoAudioDialog::handlePaletteUpdate() { // TIA Palette instance().settings().setValue("palette", @@ -704,7 +831,7 @@ void VideoDialog::handlePaletteUpdate() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleFullScreenChange() +void VideoAudioDialog::handleFullScreenChange() { bool enable = myFullscreen->getState(); myUseStretch->setEnabled(enable); @@ -712,7 +839,7 @@ void VideoDialog::handleFullScreenChange() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleOverscanChange() +void VideoAudioDialog::handleOverscanChange() { if (myTVOverscan->getValue() == 0) { @@ -724,13 +851,13 @@ void VideoDialog::handleOverscanChange() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handlePhosphorChange() +void VideoAudioDialog::handlePhosphorChange() { myTVPhosLevel->setEnabled(myTVPhosphor->getState()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleCommand(CommandSender* sender, int cmd, +void VideoAudioDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) { switch (cmd) @@ -793,11 +920,6 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd, myVSizeAdjust->setValueUnit("%"); break; } - - case kSpeedupChanged: - mySpeed->setValueLabel(formatSpeed(mySpeed->getValue())); - break; - case kFullScreenChanged: handleFullScreenChange(); break; @@ -845,6 +967,30 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd, 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; @@ -852,7 +998,7 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::addPalette(int x, int y, int w, int h) +void VideoAudioDialog::addPalette(int x, int y, int w, int h) { if(instance().hasConsole()) { @@ -877,7 +1023,7 @@ void VideoDialog::addPalette(int x, int y, int w, int h) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::colorPalette() +void VideoAudioDialog::colorPalette() { if(instance().hasConsole()) { @@ -904,3 +1050,37 @@ void VideoDialog::colorPalette() } } } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +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 75% rename from src/gui/VideoDialog.hxx rename to src/gui/VideoAudioDialog.hxx index 7d01b6808..6380ae352 100644 --- a/src/gui/VideoDialog.hxx +++ b/src/gui/VideoAudioDialog.hxx @@ -15,8 +15,8 @@ // 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; @@ -34,21 +34,22 @@ class OSystem; #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 addGeneralTab(); + void addDisplayTab(); void addPaletteTab(); void addTVEffectsTab(); + void addAudioTab(); void handleTVModeChange(NTSCFilter::Preset); void loadTVAdjustables(NTSCFilter::Preset preset); void handlePaletteChange(); @@ -59,45 +60,30 @@ class VideoDialog : public Dialog 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}; - - RadioButtonGroup* myZoomGroup{nullptr}; CheckboxWidget* myFullscreen{nullptr}; //PopUpWidget* myFullScreenMode; CheckboxWidget* myUseStretch{nullptr}; SliderWidget* myTVOverscan{nullptr}; - CheckboxWidget* myUseVSync{nullptr}; - CheckboxWidget* myUIMessages{nullptr}; - CheckboxWidget* myFastSCBios{nullptr}; - CheckboxWidget* myUseThreads{nullptr}; - std::array myColorLbl{nullptr}; - //std::array myColor{nullptr}; - ColorWidget* myColor[16][8]{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}; @@ -114,19 +100,43 @@ 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{0.0F}; enum { + kZoomChanged = 'VDZo', + kVSizeChanged = 'VDVs', + kFullScreenChanged = 'VDFs', + kOverscanChanged = 'VDOv', + kPaletteChanged = 'VDpl', kNtscShiftChanged = 'VDns', kPalShiftChanged = 'VDps', kPaletteUpdated = 'VDpu', - kSpeedupChanged = 'VDSp', - kVSizeChanged = 'VDVs', - kFullScreenChanged = 'VDFs', - kZoomChanged = 'VDZo', - kOverscanChanged = 'VDOv', kTVModeChanged = 'VDtv', kCloneCompositeCmd = 'CLcp', @@ -136,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/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/windows/Stella.vcxproj b/src/windows/Stella.vcxproj index bc0724d09..6fef5d589 100644 --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -758,6 +758,7 @@ + @@ -907,7 +908,6 @@ true - @@ -939,7 +939,7 @@ - + CompileAsC @@ -1791,6 +1791,7 @@ + @@ -1967,7 +1968,6 @@ - @@ -2003,7 +2003,7 @@ - + diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters index 62e324fa4..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 @@ -1005,6 +999,12 @@ Source Files + + Source Files\gui + + + Source Files\gui + @@ -1316,9 +1316,6 @@ Header Files\gui - - Header Files\gui - Header Files\gui @@ -1424,9 +1421,6 @@ Header Files\gui - - Header Files\gui - Header Files\gui @@ -2063,6 +2057,12 @@ Header Files + + Header Files\gui + + + Header Files\gui + From c078bf135d2f7ad73440346c6ed9bc601cb71c1d Mon Sep 17 00:00:00 2001 From: thrust26 Date: Mon, 11 May 2020 16:18:43 +0200 Subject: [PATCH 10/14] bugfix audio widgets enabling --- src/gui/VideoAudioDialog.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/VideoAudioDialog.cxx b/src/gui/VideoAudioDialog.cxx index dbab74acf..b5f155f40 100644 --- a/src/gui/VideoAudioDialog.cxx +++ b/src/gui/VideoAudioDialog.cxx @@ -537,7 +537,7 @@ void VideoAudioDialog::loadConfig() AudioSettings& audioSettings = instance().audioSettings(); // Enable sound -#ifndef SOUND_SUPPORT +#ifdef SOUND_SUPPORT mySoundEnableCheckbox->setState(audioSettings.enabled()); #else mySoundEnableCheckbox->setState(false); From 5ddaea992daaaaccf9880e614dc1a49ddcadc8d5 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Mon, 11 May 2020 14:57:01 -0230 Subject: [PATCH 11/14] Fixes for warnings in latest g++ and clang, and update libretro port to latest changes. --- src/common/PKeyboardHandler.cxx | 2 ++ src/common/PaletteHandler.cxx | 37 +++++++++++++++-------------- src/common/PaletteHandler.hxx | 26 ++++++++++---------- src/debugger/gui/CartARWidget.cxx | 2 ++ src/debugger/gui/CartE0Widget.cxx | 2 +- src/debugger/gui/DebuggerDialog.hxx | 2 +- src/emucore/PointingDevice.cxx | 2 ++ src/emucore/TIASurface.hxx | 2 +- src/emucore/Thumbulator.cxx | 1 + src/gui/ColorWidget.cxx | 4 ++-- src/gui/DialogContainer.cxx | 1 - src/gui/EmulationDialog.cxx | 2 +- src/gui/VideoAudioDialog.cxx | 6 ++--- src/gui/VideoAudioDialog.hxx | 4 ++-- src/libretro/Makefile.common | 1 + src/libretro/StellaLIBRETRO.cxx | 13 +++------- src/libretro/StellaLIBRETRO.hxx | 2 +- src/libretro/libretro.cxx | 18 ++++++-------- 18 files changed, 61 insertions(+), 66 deletions(-) diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx index 3edd7698d..9384d3232 100644 --- a/src/common/PKeyboardHandler.cxx +++ b/src/common/PKeyboardHandler.cxx @@ -15,6 +15,8 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "OSystem.hxx" +#include "Console.hxx" #include "EventHandler.hxx" #include "PKeyboardHandler.hxx" diff --git a/src/common/PaletteHandler.cxx b/src/common/PaletteHandler.cxx index 3f1066724..2aecc6abf 100644 --- a/src/common/PaletteHandler.cxx +++ b/src/common/PaletteHandler.cxx @@ -15,6 +15,7 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include #include "Console.hxx" #include "FrameBuffer.hxx" @@ -303,7 +304,7 @@ PaletteArray PaletteHandler::adjustedPalette(const PaletteArray& palette) adjust[i] = powf(i * toFloat, gamma) * contrast + brightness; // Transform original palette into destination palette - for(int i = 0; i < destPalette.size(); i += 2) + for(size_t i = 0; i < destPalette.size(); i += 2) { const uInt32 pixel = palette[i]; int r = (pixel >> 16) & 0xff; @@ -396,8 +397,8 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) // 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)); + 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++) @@ -488,17 +489,17 @@ void PaletteHandler::adjustHueSaturation(int& R, int& G, int& B, float H, float // Adapted from http://beesbuzz.biz/code/16-hsv-color-transforms // (C) J. “Fluffy” Shagam // License: CC BY-SA 4.0 - const float su = S * cos(-H * BSPF::PI_f); - const float sw = S * sin(-H * BSPF::PI_f); - const float r = (.299 + .701 * su + .168 * sw) * R - + (.587 - .587 * su + .330 * sw) * G - + (.114 - .114 * su - .497 * sw) * B; - const float g = (.299 - .299 * su - .328 * sw) * R - + (.587 + .413 * su + .035 * sw) * G - + (.114 - .114 * su + .292 * sw) * B; - const float b = (.299 - .300 * su + 1.25 * sw) * R - + (.587 - .588 * su - 1.05 * sw) * G - + (.114 + .886 * su - .203 * sw) * B; + 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); @@ -724,14 +725,14 @@ const PaletteArray PaletteHandler::ourSECAMPaletteZ26 = { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 index 237d9b878..3a8c5c9e3 100644 --- a/src/common/PaletteHandler.hxx +++ b/src/common/PaletteHandler.hxx @@ -38,8 +38,8 @@ class PaletteHandler // Externally used adjustment parameters struct Adjustable { - float phaseNtsc, phasePal; - uInt32 hue, saturation, contrast, brightness, gamma; + float phaseNtsc{0.F}, phasePal{0.F}; + uInt32 hue{0}, saturation{0}, contrast{0}, brightness{0}, gamma{0}; }; public: @@ -54,14 +54,14 @@ class PaletteHandler void cyclePalette(bool next = true); /* - Cycle through each palette adjustable + Cycle through each palette adjustable. @param next Select next adjustable, else previous one */ void cycleAdjustable(bool next = true); /* - Increase or decrease current palette adjustable + Increase or decrease current palette adjustable. @param increase Increase adjustable if true, else decrease */ @@ -82,7 +82,7 @@ class PaletteHandler /** Sets the palette according to the given palette name. - @param palette The palette to switch to. + @param name The palette to switch to */ void setPalette(const string& name); @@ -107,11 +107,11 @@ class PaletteHandler /** Convert adjustables from/to 100% scale */ - float scaleFrom100(float x) const { return (x / 50.F) - 1.F; } - uInt32 scaleTo100(float x) const { return uInt32(50 * (x + 1.F)); } + 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 + Convert palette settings name to enumeration. @param name The given palette's settings name @@ -120,7 +120,7 @@ class PaletteHandler PaletteType toPaletteType(const string& name) const; /** - Convert enumeration to palette settings name + Convert enumeration to palette settings name. @param type The given palette type @@ -133,7 +133,7 @@ class PaletteHandler 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. + @param increase Increase if true, else decrease */ void changeColorPhaseShift(bool increase = true); @@ -145,16 +145,16 @@ class PaletteHandler void generateCustomPalette(ConsoleTiming timing); /** - Create new palette by applying palette adjustments on given palette + Create new palette by applying palette adjustments on given palette. - @param type The palette which should be adjusted + @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 + Adjust hue and saturation for given RGB values. @param R The red value to adjust @param G The green value to adjust 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/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/DebuggerDialog.hxx b/src/debugger/gui/DebuggerDialog.hxx index bfd7c332b..b66ae37a6 100644 --- a/src/debugger/gui/DebuggerDialog.hxx +++ b/src/debugger/gui/DebuggerDialog.hxx @@ -33,7 +33,6 @@ class TiaOutputWidget; class TiaZoomWidget; class CartDebugWidget; class CartRamWidget; -class OptionsDialog; namespace Common { struct Rect; @@ -41,6 +40,7 @@ namespace Common { #include "Dialog.hxx" #include "MessageBox.hxx" +#include "OptionsDialog.hxx" class DebuggerDialog : public Dialog { 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/TIASurface.hxx b/src/emucore/TIASurface.hxx index 9dbda5b14..6552c26ca 100644 --- a/src/emucore/TIASurface.hxx +++ b/src/emucore/TIASurface.hxx @@ -22,13 +22,13 @@ class TIA; class Console; class OSystem; class FBSurface; -class PaletteHandler; #include #include "Rect.hxx" #include "FrameBuffer.hxx" #include "NTSCFilter.hxx" +#include "PaletteHandler.hxx" #include "PhosphorHandler.hxx" #include "bspf.hxx" #include "TIAConstants.hxx" 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/ColorWidget.cxx b/src/gui/ColorWidget.cxx index 8052bf029..27f4bc3cf 100644 --- a/src/gui/ColorWidget.cxx +++ b/src/gui/ColorWidget.cxx @@ -28,8 +28,8 @@ ColorWidget::ColorWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h, int cmd, bool framed) : Widget(boss, font, x, y, w, h), CommandSender(boss), - _cmd(cmd), - _framed(framed) + _framed(framed), + _cmd(cmd) { _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS; } 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 index 111fa12f9..ad86e2e60 100644 --- a/src/gui/EmulationDialog.cxx +++ b/src/gui/EmulationDialog.cxx @@ -280,4 +280,4 @@ void EmulationDialog::handleCommand(CommandSender* sender, int cmd, Dialog::handleCommand(sender, cmd, data, 0); break; } -} \ No newline at end of file +} diff --git a/src/gui/VideoAudioDialog.cxx b/src/gui/VideoAudioDialog.cxx index b5f155f40..5d569014a 100644 --- a/src/gui/VideoAudioDialog.cxx +++ b/src/gui/VideoAudioDialog.cxx @@ -112,8 +112,7 @@ void VideoAudioDialog::addDisplayTab() { const int lineHeight = _font.getLineHeight(), fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(), - buttonHeight = _font.getLineHeight() * 1.25; + fontWidth = _font.getMaxCharWidth(); const int VGAP = fontHeight / 4; const int VBORDER = fontHeight / 2; const int HBORDER = fontWidth * 1.25; @@ -186,8 +185,7 @@ void VideoAudioDialog::addPaletteTab() { const int lineHeight = _font.getLineHeight(), fontHeight = _font.getFontHeight(), - fontWidth = _font.getMaxCharWidth(), - buttonHeight = _font.getLineHeight() * 1.25; + fontWidth = _font.getMaxCharWidth(); const int VBORDER = fontHeight / 2; const int HBORDER = fontWidth * 1.25; const int INDENT = fontWidth * 2; diff --git a/src/gui/VideoAudioDialog.hxx b/src/gui/VideoAudioDialog.hxx index 6380ae352..f46740ae6 100644 --- a/src/gui/VideoAudioDialog.hxx +++ b/src/gui/VideoAudioDialog.hxx @@ -110,7 +110,7 @@ class VideoAudioDialog : public Dialog SliderWidget* myTVContrast{nullptr}; SliderWidget* myTVGamma{nullptr}; std::array myColorLbl{nullptr}; - ColorWidget* myColor[16][8]{nullptr}; + ColorWidget* myColor[16][8]{{nullptr}}; // Audio CheckboxWidget* mySoundEnableCheckbox{nullptr}; @@ -125,7 +125,7 @@ class VideoAudioDialog : public Dialog SliderWidget* myDpcPitch{nullptr}; string myPalette; - PaletteHandler::Adjustable myPaletteAdj{0.0F}; + PaletteHandler::Adjustable myPaletteAdj; enum { kZoomChanged = 'VDZo', 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" }, From 9b933ec4d484cc3c96c4242a5f62c11fa5095c82 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Mon, 11 May 2020 15:33:42 -0230 Subject: [PATCH 12/14] Update Xcode project for class changes. --- src/debugger/DiStella.cxx | 2 +- src/macos/stella.xcodeproj/project.pbxproj | 96 +++++++++++----------- 2 files changed, 49 insertions(+), 49 deletions(-) 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/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 */, From 08c48c5f82646feef69ef87a20ac43f8cfbda109 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Mon, 11 May 2020 16:15:34 -0230 Subject: [PATCH 13/14] Don't include some header files when we don't need to. --- src/debugger/gui/DebuggerDialog.cxx | 5 +++++ src/debugger/gui/DebuggerDialog.hxx | 8 +++++--- src/emucore/TIASurface.cxx | 5 +++++ src/emucore/TIASurface.hxx | 5 ++--- 4 files changed, 17 insertions(+), 6 deletions(-) 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/TIASurface.cxx b/src/emucore/TIASurface.cxx index 19e817b0d..8ff9f3e17 100644 --- a/src/emucore/TIASurface.cxx +++ b/src/emucore/TIASurface.cxx @@ -82,6 +82,11 @@ TIASurface::TIASurface(OSystem& system) myPaletteHandler->loadConfig(myOSystem.settings()); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TIASurface::~TIASurface() +{ +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TIASurface::initialize(const Console& console, const FrameBuffer::VideoMode& mode) diff --git a/src/emucore/TIASurface.hxx b/src/emucore/TIASurface.hxx index 6552c26ca..b2c00f912 100644 --- a/src/emucore/TIASurface.hxx +++ b/src/emucore/TIASurface.hxx @@ -22,13 +22,13 @@ class TIA; class Console; class OSystem; class FBSurface; +class PaletteHandler; #include #include "Rect.hxx" #include "FrameBuffer.hxx" #include "NTSCFilter.hxx" -#include "PaletteHandler.hxx" #include "PhosphorHandler.hxx" #include "bspf.hxx" #include "TIAConstants.hxx" @@ -49,8 +49,7 @@ class TIASurface Creates a new TIASurface object */ explicit TIASurface(OSystem& system); - - virtual ~TIASurface() = default; + virtual ~TIASurface(); /** Set the TIA object, which is needed for actually rendering the TIA image. From 36c18c2e281d6fa5386cd4b871b357889638768f Mon Sep 17 00:00:00 2001 From: thrust26 Date: Mon, 11 May 2020 21:18:49 +0200 Subject: [PATCH 14/14] Fixed minimal zoom and message area width --- Changes.txt | 2 ++ src/emucore/FrameBuffer.cxx | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) 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/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