//============================================================================ // // SSSS tt lll lll // SS SS tt ll ll // SS tttttt eeee ll ll aaaa // SSSS tt ee ee ll ll aa // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" // SS SS tt ee ll ll aa aa // SSSS ttt eeeee llll llll aaaaa // // Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony // and the Stella Team // // See the file "License.txt" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ #ifndef PALETTE_HANDLER_HXX #define PALETTE_HANDLER_HXX #include "bspf.hxx" #include "OSystem.hxx" #include "ConsoleTiming.hxx" #include "EventHandlerConstants.hxx" class PaletteHandler { public: // Setting names of palette types static constexpr const char* SETTING_STANDARD = "standard"; static constexpr const char* SETTING_Z26 = "z26"; static constexpr const char* SETTING_USER = "user"; static constexpr const char* SETTING_CUSTOM = "custom"; // Phase shift default and limits static constexpr float DEF_NTSC_SHIFT = 26.2F; static constexpr float DEF_PAL_SHIFT = 31.3F; // ~= 360 / 11.5 static constexpr float MAX_PHASE_SHIFT = 4.5F; static constexpr float DEF_RGB_SHIFT = 0.0F; static constexpr float MAX_RGB_SHIFT = 22.5F; enum Adjustables { PHASE_SHIFT, RED_SCALE, GREEN_SCALE, BLUE_SCALE, RED_SHIFT, GREEN_SHIFT, BLUE_SHIFT, HUE, SATURATION, CONTRAST, BRIGHTNESS, GAMMA, CUSTOM_START = PHASE_SHIFT, CUSTOM_END = BLUE_SHIFT, }; // Externally used adjustment parameters struct Adjustable { float phaseNtsc{0.F}, phasePal{0.F}, redScale{0.F}, greenScale{0.F}, blueScale{0.F}, redShift{0.F}, greenShift{0.F}, blueShift{0.F}; uInt32 hue{0}, saturation{0}, contrast{0}, brightness{0}, gamma{0}; }; public: PaletteHandler(OSystem& system); /** Cycle through available palettes. @param direction +1 indicates increase, -1 indicates decrease. */ void cyclePalette(int direction = +1); /* Cycle through each palette adjustable. @param direction +1 indicates increase, -1 indicates decrease. */ void cycleAdjustable(int direction = +1); /* Increase or decrease given palette adjustable. @param adjustable The adjustable to change @param direction +1 indicates increase, -1 indicates decrease. */ void changeAdjustable(int adjustable, int direction); /* Increase or decrease current palette adjustable. @param direction +1 indicates increase, -1 indicates decrease. */ void changeCurrentAdjustable(int direction = +1); // Load adjustables from settings void loadConfig(const Settings& settings); // Save adjustables to settings void saveConfig(Settings& settings) const; // Set adjustables void setAdjustables(const Adjustable& adjustable); // Retrieve current adjustables void getAdjustables(Adjustable& adjustable) const; /** Sets the palette according to the given palette name. @param name The palette to switch to */ void setPalette(const string& name); /** Sets the palette from current settings. */ void setPalette(); private: static constexpr char DEGREE = 0x1c; enum PaletteType { Standard, Z26, User, Custom, NumTypes, MinType = Standard, MaxType = Custom }; struct vector2d { float x{0.F}; float y{0.F}; explicit vector2d(float _x = 0.F, float _y = 0.F) : x(_x), y(_y) { } }; /** Convert RGB adjustables from/to 100% scale */ static constexpr float scaleRGBFrom100(float x) { return x / 50.F; } static constexpr uInt32 scaleRGBTo100(float x) { return uInt32(50.0001F * (x - 0.F)); } /** Convert angles */ static constexpr float scaleFromAngles(float x) { return x / 10.F; } static constexpr Int32 scaleToAngles(float x) { return uInt32(10.F * x); } /** Convert adjustables from/to 100% scale */ static constexpr float scaleFrom100(float x) { return (x / 50.F) - 1.F; } static constexpr uInt32 scaleTo100(float x) { return uInt32(50.0001F * (x + 1.F)); } /** Check for 'Custom' palette only adjustables */ bool isCustomAdjustable() const; bool isPhaseShift() const; bool isRGBScale() const; bool isRGBShift() const; /** 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; /** Display current adjustable with gauge bar message */ void showAdjustableMessage(); /** 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 = +1); /** Generates a custom palette, based on user defined phase shifts. @param timing Use NTSC or PAL phase shift and generate according palette */ void generateCustomPalette(ConsoleTiming timing); /** Create new palette by applying palette adjustments on given palette. @param source The palette which should be adjusted @return An adjusted palette */ PaletteArray adjustedPalette(const PaletteArray& source); /** Adjust hue and saturation for given RGB values. @param R The red value to adjust @param G The green value to adjust @param B The blue value to adjust @param H The hue adjustment value @param S The saturation */ void adjustHueSaturation(int& R, int& G, int& B, float H, float S); /** Rotate a 2D vector. */ vector2d rotate(const vector2d& vec, float angle) const; /** Scale a 2D vector. */ vector2d scale(const vector2d& vec, float factor) const; /** Get the dot product of two 2D vectors. */ float dotProduct(const vector2d& vec1, const vector2d& vec2) const; /** Loads a user-defined palette file (from OSystem::paletteFile), filling the appropriate user-defined palette arrays. */ void loadUserPalette(); private: static constexpr int NUM_ADJUSTABLES = 12; OSystem& myOSystem; // The currently selected adjustable uInt32 myCurrentAdjustable{0}; struct AdjustableTag { const char* const name{nullptr}; float* value{nullptr}; }; const std::array myAdjustables = { { { "phase shift", nullptr }, { "red scale", &myRedScale }, { "green scale", &myGreenScale }, { "blue scale", &myBlueScale }, { "red shift", &myRedShift }, { "green shift", &myGreenShift }, { "blue shift", &myBlueShift }, { "hue", &myHue }, { "saturation", &mySaturation }, { "contrast", &myContrast }, { "brightness", &myBrightness }, { "gamma", &myGamma }, } }; // NTSC and PAL color phase shifts float myPhaseNTSC{DEF_NTSC_SHIFT}; float myPhasePAL{DEF_PAL_SHIFT}; // Color intensities float myRedScale{1.0F}; float myGreenScale{1.0F}; float myBlueScale{1.0F}; // Color shifts float myRedShift{0.0F}; float myGreenShift{0.0F}; float myBlueShift{0.0F}; // range -1.0 to +1.0 (as in AtariNTSC) // Basic parameters float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees float mySaturation{0.0F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0) float myContrast{0.0F}; // -1 = dark (0.5) +1 = light (1.5) float myBrightness{0.0F}; // -1 = dark (0.5) +1 = light (1.5) // Advanced parameters float myGamma{0.0F}; // -1 = dark (1.5) +1 = light (0.5) // Indicates whether an external palette was found and // successfully loaded bool myUserPaletteDefined{false}; // Table of RGB values for NTSC, PAL and SECAM static const PaletteArray ourNTSCPalette; static const PaletteArray ourPALPalette; static const PaletteArray ourSECAMPalette; // Table of RGB values for NTSC, PAL and SECAM - Z26 version static const PaletteArray ourNTSCPaletteZ26; static const PaletteArray ourPALPaletteZ26; static const PaletteArray ourSECAMPaletteZ26; // Table of RGB values for NTSC, PAL and SECAM - user-defined static PaletteArray ourUserNTSCPalette; static PaletteArray ourUserPALPalette; static PaletteArray ourUserSECAMPalette; // Table of RGB values for NTSC, PAL - custom-defined and generated static PaletteArray ourCustomNTSCPalette; static PaletteArray ourCustomPALPalette; private: PaletteHandler() = delete; PaletteHandler(const PaletteHandler&) = delete; PaletteHandler(PaletteHandler&&) = delete; PaletteHandler& operator=(const PaletteHandler&) = delete; PaletteHandler& operator=(const PaletteHandler&&) = delete; }; #endif // PALETTE_HANDLER_HXX