mirror of https://github.com/stella-emu/stella.git
Refactored phosphor calculations into a new PhosphorHandler class.
This class is accessible from both TIASurface and AtariNTSC, so there's no more code duplication. Testing is required to see if this results in any slowdowns. It shouldn't, since the relevant code is inlined ...
This commit is contained in:
parent
bf3f146076
commit
74a2e4b9a9
|
@ -0,0 +1,56 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// 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-2019 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 "PhosphorHandler.hxx"
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
PhosphorHandler::PhosphorHandler()
|
||||||
|
: myUsePhosphor(false),
|
||||||
|
myPhosphorPercent(0.60F)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool PhosphorHandler::initialize(bool enable, int blend)
|
||||||
|
{
|
||||||
|
if(myUsePhosphor == enable && myPhosphorPercent == blend / 100.F)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
myUsePhosphor = enable;
|
||||||
|
if(blend >= 0 && blend <= 100)
|
||||||
|
myPhosphorPercent = blend / 100.F;
|
||||||
|
|
||||||
|
// Used to calculate an averaged color for the 'phosphor' effect
|
||||||
|
auto getPhosphor = [&] (const uInt8 c1, uInt8 c2) -> uInt8 {
|
||||||
|
// Use maximum of current and decayed previous values
|
||||||
|
c2 = static_cast<uInt8>(c2 * myPhosphorPercent);
|
||||||
|
if(c1 > c2) return c1; // raise (assumed immediate)
|
||||||
|
else return c2; // decay
|
||||||
|
};
|
||||||
|
|
||||||
|
// Precalculate the average colors for the 'phosphor' effect
|
||||||
|
if(myUsePhosphor)
|
||||||
|
{
|
||||||
|
for(int c = 255; c >= 0; --c)
|
||||||
|
for(int p = 255; p >= 0; --p)
|
||||||
|
ourPhosphorLUT[c][p] = getPhosphor(uInt8(c), uInt8(p));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
PhosphorHandler::PhosphorLUT PhosphorHandler::ourPhosphorLUT;
|
|
@ -0,0 +1,73 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// 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-2019 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 PHOSPHOR_HANDLER_HXX
|
||||||
|
#define PHOSPHOR_HANDLER_HXX
|
||||||
|
|
||||||
|
#include "FrameBufferConstants.hxx"
|
||||||
|
#include "bspf.hxx"
|
||||||
|
|
||||||
|
class PhosphorHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PhosphorHandler();
|
||||||
|
|
||||||
|
bool initialize(bool enable, int blend);
|
||||||
|
|
||||||
|
bool phosphorEnabled() const { return myUsePhosphor; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Used to calculate an averaged color pixel for the 'phosphor' effect.
|
||||||
|
|
||||||
|
@param c RGB Color 1 (current frame)
|
||||||
|
@param p RGB Color 2 (previous frame)
|
||||||
|
|
||||||
|
@return Averaged value of the two RGB colors
|
||||||
|
*/
|
||||||
|
static inline uInt32 getPixel(const uInt32 c, const uInt32 p)
|
||||||
|
{
|
||||||
|
// Mix current calculated frame with previous displayed frame
|
||||||
|
const uInt8 rc = static_cast<uInt8>(c >> 16),
|
||||||
|
gc = static_cast<uInt8>(c >> 8),
|
||||||
|
bc = static_cast<uInt8>(c),
|
||||||
|
rp = static_cast<uInt8>(p >> 16),
|
||||||
|
gp = static_cast<uInt8>(p >> 8),
|
||||||
|
bp = static_cast<uInt8>(p);
|
||||||
|
|
||||||
|
return (ourPhosphorLUT[rc][rp] << 16) | (ourPhosphorLUT[gc][gp] << 8) |
|
||||||
|
ourPhosphorLUT[bc][bp];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Use phosphor effect
|
||||||
|
bool myUsePhosphor;
|
||||||
|
|
||||||
|
// Amount to blend when using phosphor effect
|
||||||
|
float myPhosphorPercent;
|
||||||
|
|
||||||
|
// Precalculated averaged phosphor colors
|
||||||
|
using PhosphorLUT = std::array<std::array<uInt8, kColor>, kColor>;
|
||||||
|
static PhosphorLUT ourPhosphorLUT;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PhosphorHandler(const PhosphorHandler&) = delete;
|
||||||
|
PhosphorHandler(PhosphorHandler&&) = delete;
|
||||||
|
PhosphorHandler& operator=(const PhosphorHandler&) = delete;
|
||||||
|
PhosphorHandler& operator=(const PhosphorHandler&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PHOSPHOR_HANDLER_HXX
|
|
@ -11,6 +11,7 @@ MODULE_OBJS := \
|
||||||
src/common/Logger.o \
|
src/common/Logger.o \
|
||||||
src/common/main.o \
|
src/common/main.o \
|
||||||
src/common/MouseControl.o \
|
src/common/MouseControl.o \
|
||||||
|
src/common/PhosphorHandler.o \
|
||||||
src/common/PhysicalJoystick.o \
|
src/common/PhysicalJoystick.o \
|
||||||
src/common/PJoystickHandler.o \
|
src/common/PJoystickHandler.o \
|
||||||
src/common/PKeyboardHandler.o \
|
src/common/PKeyboardHandler.o \
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include "AtariNTSC.hxx"
|
#include "AtariNTSC.hxx"
|
||||||
|
#include "PhosphorHandler.hxx"
|
||||||
|
|
||||||
// blitter related
|
// blitter related
|
||||||
#ifndef restrict
|
#ifndef restrict
|
||||||
|
@ -50,12 +51,6 @@ void AtariNTSC::setPalette(const PaletteArray& palette)
|
||||||
generateKernels();
|
generateKernels();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void AtariNTSC::setPhosphorTable(const PhosphorLUT& table)
|
|
||||||
{
|
|
||||||
myPhosphorLUT = table;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void AtariNTSC::generateKernels()
|
void AtariNTSC::generateKernels()
|
||||||
{
|
{
|
||||||
|
@ -281,38 +276,38 @@ void AtariNTSC::renderWithPhosphorThread(const uInt8* atari_in, const uInt32 in_
|
||||||
for (uInt32 x = AtariNTSC::outWidth(in_width) / 8; x; --x)
|
for (uInt32 x = AtariNTSC::outWidth(in_width) / 8; x; --x)
|
||||||
{
|
{
|
||||||
// Store back into displayed frame buffer (for next frame)
|
// Store back into displayed frame buffer (for next frame)
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
}
|
}
|
||||||
// finish final 565 % 8 = 5 pixels
|
// finish final 565 % 8 = 5 pixels
|
||||||
/*rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
/*rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;*/
|
++bufofs;*/
|
||||||
#if 0
|
#if 0
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgb_in[bufofs] = getRGBPhosphor(out[bufofs], rgb_in[bufofs]);
|
rgb_in[bufofs] = PhosphorHandler::getPixel(out[bufofs], rgb_in[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -321,21 +316,6 @@ void AtariNTSC::renderWithPhosphorThread(const uInt8* atari_in, const uInt32 in_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
inline uInt32 AtariNTSC::getRGBPhosphor(const uInt32 c, const uInt32 p) const
|
|
||||||
{
|
|
||||||
// Mix current calculated frame with previous displayed frame
|
|
||||||
const uInt8 rc = static_cast<uInt8>(c >> 16),
|
|
||||||
gc = static_cast<uInt8>(c >> 8),
|
|
||||||
bc = static_cast<uInt8>(c),
|
|
||||||
rp = static_cast<uInt8>(p >> 16),
|
|
||||||
gp = static_cast<uInt8>(p >> 8),
|
|
||||||
bp = static_cast<uInt8>(p);
|
|
||||||
|
|
||||||
return (myPhosphorLUT[rc][rp] << 16) | (myPhosphorLUT[gc][gp] << 8) |
|
|
||||||
myPhosphorLUT[bc][bp];
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void AtariNTSC::init(init_t& impl, const Setup& setup)
|
void AtariNTSC::init(init_t& impl, const Setup& setup)
|
||||||
{
|
{
|
||||||
|
|
|
@ -83,8 +83,6 @@ class AtariNTSC
|
||||||
|
|
||||||
// Set palette for normal Blarrg mode
|
// Set palette for normal Blarrg mode
|
||||||
void setPalette(const PaletteArray& palette);
|
void setPalette(const PaletteArray& palette);
|
||||||
// Set phosphor table, for use in calculating phosphor palette
|
|
||||||
void setPhosphorTable(const PhosphorLUT& table);
|
|
||||||
|
|
||||||
// Set up threading
|
// Set up threading
|
||||||
void enableThreading(bool enable);
|
void enableThreading(bool enable);
|
||||||
|
@ -96,13 +94,6 @@ class AtariNTSC
|
||||||
void render(const uInt8* atari_in, const uInt32 in_width, const uInt32 in_height,
|
void render(const uInt8* atari_in, const uInt32 in_width, const uInt32 in_height,
|
||||||
void* rgb_out, const uInt32 out_pitch, uInt32* rgb_in = nullptr);
|
void* rgb_out, const uInt32 out_pitch, uInt32* rgb_in = nullptr);
|
||||||
|
|
||||||
// Number of input pixels that will fit within given output width.
|
|
||||||
// Might be rounded down slightly; use outWidth() on result to find
|
|
||||||
// rounded value.
|
|
||||||
/*static constexpr uInt32 inWidth( uInt32 out_width ) {
|
|
||||||
return (((out_width - 8) / PIXEL_out_chunk - 1) * PIXEL_in_chunk + 1);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// Number of output pixels written by blitter for given input width.
|
// Number of output pixels written by blitter for given input width.
|
||||||
// Width might be rounded down slightly; use inWidth() on result to
|
// Width might be rounded down slightly; use inWidth() on result to
|
||||||
// find rounded value. Guaranteed not to round 160 down at all.
|
// find rounded value. Guaranteed not to round 160 down at all.
|
||||||
|
@ -120,16 +111,6 @@ class AtariNTSC
|
||||||
void renderWithPhosphorThread(const uInt8* atari_in, const uInt32 in_width,
|
void renderWithPhosphorThread(const uInt8* atari_in, const uInt32 in_width,
|
||||||
const uInt32 in_height, const uInt32 numThreads, const uInt32 threadNum, uInt32* rgb_in, void* rgb_out, const uInt32 out_pitch);
|
const uInt32 in_height, const uInt32 numThreads, const uInt32 threadNum, uInt32* rgb_in, void* rgb_out, const uInt32 out_pitch);
|
||||||
|
|
||||||
/**
|
|
||||||
Used to calculate an averaged color for the 'phosphor' effect.
|
|
||||||
|
|
||||||
@param c RGB Color 1 (current frame)
|
|
||||||
@param cp RGB Color 2 (previous frame)
|
|
||||||
|
|
||||||
@return Averaged value of the two RGB colors
|
|
||||||
*/
|
|
||||||
uInt32 getRGBPhosphor(const uInt32 c, const uInt32 cp) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr Int32
|
static constexpr Int32
|
||||||
PIXEL_in_chunk = 2, // number of input pixels read per chunk
|
PIXEL_in_chunk = 2, // number of input pixels read per chunk
|
||||||
|
@ -172,7 +153,6 @@ class AtariNTSC
|
||||||
|
|
||||||
std::array<uInt8, palette_size*3> myRGBPalette;
|
std::array<uInt8, palette_size*3> myRGBPalette;
|
||||||
std::array<std::array<uInt32, entry_size>, palette_size> myColorTable;
|
std::array<std::array<uInt32, entry_size>, palette_size> myColorTable;
|
||||||
PhosphorLUT myPhosphorLUT;
|
|
||||||
|
|
||||||
// Rendering threads
|
// Rendering threads
|
||||||
unique_ptr<std::thread[]> myThreads;
|
unique_ptr<std::thread[]> myThreads;
|
||||||
|
@ -277,6 +257,13 @@ class AtariNTSC
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // DEAD CODE
|
#if 0 // DEAD CODE
|
||||||
|
// Number of input pixels that will fit within given output width.
|
||||||
|
// Might be rounded down slightly; use outWidth() on result to find
|
||||||
|
// rounded value.
|
||||||
|
static constexpr uInt32 inWidth( uInt32 out_width ) {
|
||||||
|
return (((out_width - 8) / PIXEL_out_chunk - 1) * PIXEL_in_chunk + 1);
|
||||||
|
}
|
||||||
|
|
||||||
#define ROTATE_IQ( i, q, sin_b, cos_b ) {\
|
#define ROTATE_IQ( i, q, sin_b, cos_b ) {\
|
||||||
float t;\
|
float t;\
|
||||||
t = i * cos_b - q * sin_b;\
|
t = i * cos_b - q * sin_b;\
|
||||||
|
|
|
@ -63,9 +63,6 @@ class NTSCFilter
|
||||||
void setPalette(const PaletteArray& palette) {
|
void setPalette(const PaletteArray& palette) {
|
||||||
myNTSC.setPalette(palette);
|
myNTSC.setPalette(palette);
|
||||||
}
|
}
|
||||||
void setPhosphorTable(const PhosphorLUT& table) {
|
|
||||||
myNTSC.setPhosphorTable(table);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The following are meant to be used strictly for toggling from the GUI
|
// The following are meant to be used strictly for toggling from the GUI
|
||||||
string setPreset(Preset preset);
|
string setPreset(Preset preset);
|
||||||
|
|
|
@ -107,9 +107,6 @@ using PaletteArray = std::array<uInt32, kColor>;
|
||||||
using UIPaletteArray = std::array<uInt32, kNumColors-kColor>;
|
using UIPaletteArray = std::array<uInt32, kNumColors-kColor>;
|
||||||
using FullPaletteArray = std::array<uInt32, kNumColors>;
|
using FullPaletteArray = std::array<uInt32, kNumColors>;
|
||||||
|
|
||||||
// Lookup table for phosphor mode, for generating corresponding palette
|
|
||||||
using PhosphorLUT = std::array<std::array<uInt8, kColor>, kColor>;
|
|
||||||
|
|
||||||
// Text alignment modes for drawString()
|
// Text alignment modes for drawString()
|
||||||
enum class TextAlign {
|
enum class TextAlign {
|
||||||
Left,
|
Left,
|
||||||
|
|
|
@ -40,8 +40,6 @@ TIASurface::TIASurface(OSystem& system)
|
||||||
myFB(system.frameBuffer()),
|
myFB(system.frameBuffer()),
|
||||||
myTIA(nullptr),
|
myTIA(nullptr),
|
||||||
myFilter(Filter::Normal),
|
myFilter(Filter::Normal),
|
||||||
myUsePhosphor(false),
|
|
||||||
myPhosphorPercent(0.60f),
|
|
||||||
myScanlinesEnabled(false),
|
myScanlinesEnabled(false),
|
||||||
mySaveSnapFlag(false)
|
mySaveSnapFlag(false)
|
||||||
{
|
{
|
||||||
|
@ -213,42 +211,13 @@ uInt32 TIASurface::enableScanlines(int relative, int absolute)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIASurface::enablePhosphor(bool enable, int blend)
|
void TIASurface::enablePhosphor(bool enable, int blend)
|
||||||
{
|
{
|
||||||
if(myUsePhosphor == enable && myPhosphorPercent == blend / 100.0f)
|
if(myPhosphorHandler.initialize(enable, blend))
|
||||||
return;
|
|
||||||
|
|
||||||
myUsePhosphor = enable;
|
|
||||||
if(blend >= 0)
|
|
||||||
myPhosphorPercent = blend / 100.0f;
|
|
||||||
myFilter = Filter(enable ? uInt8(myFilter) | 0x01 : uInt8(myFilter) & 0x10);
|
|
||||||
|
|
||||||
myRGBFramebuffer.fill(0);
|
|
||||||
|
|
||||||
// Precalculate the average colors for the 'phosphor' effect
|
|
||||||
if(myUsePhosphor)
|
|
||||||
{
|
{
|
||||||
for(int c = 255; c >= 0; --c)
|
myFilter = Filter(enable ? uInt8(myFilter) | 0x01 : uInt8(myFilter) & 0x10);
|
||||||
for(int p = 255; p >= 0; --p)
|
myRGBFramebuffer.fill(0);
|
||||||
myPhosphorLUT[c][p] = getPhosphor(uInt8(c), uInt8(p));
|
|
||||||
|
|
||||||
myNTSCFilter.setPhosphorTable(myPhosphorLUT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
inline uInt32 TIASurface::getRGBPhosphor(const uInt32 c, const uInt32 p) const
|
|
||||||
{
|
|
||||||
// Mix current calculated frame with previous displayed frame
|
|
||||||
const uInt8 rc = static_cast<uInt8>(c >> 16),
|
|
||||||
gc = static_cast<uInt8>(c >> 8),
|
|
||||||
bc = static_cast<uInt8>(c),
|
|
||||||
rp = static_cast<uInt8>(p >> 16),
|
|
||||||
gp = static_cast<uInt8>(p >> 8),
|
|
||||||
bp = static_cast<uInt8>(p);
|
|
||||||
|
|
||||||
return (myPhosphorLUT[rc][rp] << 16) | (myPhosphorLUT[gc][gp] << 8) |
|
|
||||||
myPhosphorLUT[bc][bp];
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIASurface::enableNTSC(bool enable)
|
void TIASurface::enableNTSC(bool enable)
|
||||||
{
|
{
|
||||||
|
@ -364,9 +333,9 @@ void TIASurface::render()
|
||||||
for(uInt32 x = width / 2; x ; --x)
|
for(uInt32 x = width / 2; x ; --x)
|
||||||
{
|
{
|
||||||
// Store back into displayed frame buffer (for next frame)
|
// Store back into displayed frame buffer (for next frame)
|
||||||
rgbIn[bufofs] = out[pos++] = getRGBPhosphor(myPalette[tiaIn[bufofs]], rgbIn[bufofs]);
|
rgbIn[bufofs] = out[pos++] = PhosphorHandler::getPixel(myPalette[tiaIn[bufofs]], rgbIn[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
rgbIn[bufofs] = out[pos++] = getRGBPhosphor(myPalette[tiaIn[bufofs]], rgbIn[bufofs]);
|
rgbIn[bufofs] = out[pos++] = PhosphorHandler::getPixel(myPalette[tiaIn[bufofs]], rgbIn[bufofs]);
|
||||||
++bufofs;
|
++bufofs;
|
||||||
}
|
}
|
||||||
screenofsY += outPitch;
|
screenofsY += outPitch;
|
||||||
|
@ -457,7 +426,7 @@ void TIASurface::renderForSnapshot()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(myUsePhosphor)
|
if(myPhosphorHandler.phosphorEnabled())
|
||||||
{
|
{
|
||||||
// Draw TIA image
|
// Draw TIA image
|
||||||
myTiaSurface->render();
|
myTiaSurface->render();
|
||||||
|
@ -472,5 +441,7 @@ void TIASurface::renderForSnapshot()
|
||||||
void TIASurface::updateSurfaceSettings()
|
void TIASurface::updateSurfaceSettings()
|
||||||
{
|
{
|
||||||
myTiaSurface->setScalingInterpolation(interpolationModeFromSettings(myOSystem.settings()));
|
myTiaSurface->setScalingInterpolation(interpolationModeFromSettings(myOSystem.settings()));
|
||||||
mySLineSurface->setScalingInterpolation(interpolationModeFromSettings(myOSystem.settings()));
|
mySLineSurface->setScalingInterpolation(
|
||||||
|
interpolationModeFromSettings(myOSystem.settings())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ class FBSurface;
|
||||||
#include "Rect.hxx"
|
#include "Rect.hxx"
|
||||||
#include "FrameBuffer.hxx"
|
#include "FrameBuffer.hxx"
|
||||||
#include "NTSCFilter.hxx"
|
#include "NTSCFilter.hxx"
|
||||||
|
#include "PhosphorHandler.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "TIAConstants.hxx"
|
#include "TIAConstants.hxx"
|
||||||
|
|
||||||
|
@ -105,32 +106,7 @@ class TIASurface
|
||||||
Enable/disable/query phosphor effect.
|
Enable/disable/query phosphor effect.
|
||||||
*/
|
*/
|
||||||
void enablePhosphor(bool enable, int blend = -1);
|
void enablePhosphor(bool enable, int blend = -1);
|
||||||
bool phosphorEnabled() const { return myUsePhosphor; }
|
bool phosphorEnabled() const { return myPhosphorHandler.phosphorEnabled(); }
|
||||||
|
|
||||||
/**
|
|
||||||
Used to calculate an averaged color for the 'phosphor' effect.
|
|
||||||
|
|
||||||
@param c1 Color 1
|
|
||||||
@param c2 Color 2
|
|
||||||
|
|
||||||
@return Averaged value of the two colors
|
|
||||||
*/
|
|
||||||
inline uInt8 getPhosphor(const uInt8 c1, uInt8 c2) const {
|
|
||||||
// Use maximum of current and decayed previous values
|
|
||||||
c2 = uInt8(c2 * myPhosphorPercent);
|
|
||||||
if(c1 > c2) return c1; // raise (assumed immediate)
|
|
||||||
else return c2; // decay
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Used to calculate an averaged color for the 'phosphor' effect.
|
|
||||||
|
|
||||||
@param c RGB Color 1 (current frame)
|
|
||||||
@param cp RGB Color 2 (previous frame)
|
|
||||||
|
|
||||||
@return Averaged value of the two RGB colors
|
|
||||||
*/
|
|
||||||
uInt32 getRGBPhosphor(const uInt32 c, const uInt32 cp) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enable/disable/query NTSC filtering effects.
|
Enable/disable/query NTSC filtering effects.
|
||||||
|
@ -190,19 +166,12 @@ class TIASurface
|
||||||
/////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////
|
||||||
// Phosphor mode items (aka reduced flicker on 30Hz screens)
|
// Phosphor mode items (aka reduced flicker on 30Hz screens)
|
||||||
// RGB frame buffer
|
// RGB frame buffer
|
||||||
|
PhosphorHandler myPhosphorHandler;
|
||||||
|
|
||||||
std::array<uInt32, AtariNTSC::outWidth(TIAConstants::frameBufferWidth) *
|
std::array<uInt32, AtariNTSC::outWidth(TIAConstants::frameBufferWidth) *
|
||||||
TIAConstants::frameBufferHeight> myRGBFramebuffer;
|
TIAConstants::frameBufferHeight> myRGBFramebuffer;
|
||||||
std::array<uInt32, AtariNTSC::outWidth(TIAConstants::frameBufferWidth) *
|
std::array<uInt32, AtariNTSC::outWidth(TIAConstants::frameBufferWidth) *
|
||||||
TIAConstants::frameBufferHeight> myPrevRGBFramebuffer;
|
TIAConstants::frameBufferHeight> myPrevRGBFramebuffer;
|
||||||
|
|
||||||
// Use phosphor effect
|
|
||||||
bool myUsePhosphor;
|
|
||||||
|
|
||||||
// Amount to blend when using phosphor effect
|
|
||||||
float myPhosphorPercent;
|
|
||||||
|
|
||||||
// Precalculated averaged phosphor colors
|
|
||||||
PhosphorLUT myPhosphorLUT;
|
|
||||||
/////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Use scanlines in TIA rendering mode
|
// Use scanlines in TIA rendering mode
|
||||||
|
|
|
@ -23,6 +23,7 @@ SOURCES_CXX := \
|
||||||
$(CORE_DIR)/common/KeyMap.cxx \
|
$(CORE_DIR)/common/KeyMap.cxx \
|
||||||
$(CORE_DIR)/common/Logger.cxx \
|
$(CORE_DIR)/common/Logger.cxx \
|
||||||
$(CORE_DIR)/common/MouseControl.cxx \
|
$(CORE_DIR)/common/MouseControl.cxx \
|
||||||
|
$(CORE_DIR)/common/PhosphorHandler.cxx \
|
||||||
$(CORE_DIR)/common/PhysicalJoystick.cxx \
|
$(CORE_DIR)/common/PhysicalJoystick.cxx \
|
||||||
$(CORE_DIR)/common/PJoystickHandler.cxx \
|
$(CORE_DIR)/common/PJoystickHandler.cxx \
|
||||||
$(CORE_DIR)/common/PKeyboardHandler.cxx \
|
$(CORE_DIR)/common/PKeyboardHandler.cxx \
|
||||||
|
|
Loading…
Reference in New Issue