mirror of https://github.com/stella-emu/stella.git
First pass at converting Blarrg code to proper C++. This mostly involves getting rid of macros.
This commit is contained in:
parent
9813173841
commit
e09634cb56
|
@ -43,14 +43,13 @@ void AtariNTSC::initializePalette(const uInt8* palette)
|
||||||
// Palette stores R/G/B data for 'palette_size' entries
|
// Palette stores R/G/B data for 'palette_size' entries
|
||||||
for ( uInt32 entry = 0; entry < palette_size; ++entry )
|
for ( uInt32 entry = 0; entry < palette_size; ++entry )
|
||||||
{
|
{
|
||||||
float r = myImpl.to_float [*palette++];
|
float r = myImpl.to_float [*palette++],
|
||||||
float g = myImpl.to_float [*palette++];
|
g = myImpl.to_float [*palette++],
|
||||||
float b = myImpl.to_float [*palette++];
|
b = myImpl.to_float [*palette++];
|
||||||
|
float y, i, q; RGB_TO_YIQ( r, g, b, y, i, q );
|
||||||
float y, i, q = RGB_TO_YIQ( r, g, b, y, i );
|
|
||||||
|
|
||||||
// Generate kernel
|
// Generate kernel
|
||||||
int ir, ig, ib = YIQ_TO_RGB( y, i, q, myImpl.to_rgb, int, ir, ig );
|
int ir, ig, ib; YIQ_TO_RGB( y, i, q, myImpl.to_rgb.data(), ir, ig, ib );
|
||||||
uInt32 rgb = PACK_RGB( ir, ig, ib );
|
uInt32 rgb = PACK_RGB( ir, ig, ib );
|
||||||
|
|
||||||
uInt32* kernel = myColorTable[entry];
|
uInt32* kernel = myColorTable[entry];
|
||||||
|
@ -77,7 +76,7 @@ void AtariNTSC::enableThreading(bool enable)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
systemThreads = std::max(1u, std::min(4u, systemThreads - 1));
|
systemThreads = std::max<uInt32>(1, std::min<uInt32>(4, systemThreads - 1));
|
||||||
|
|
||||||
myWorkerThreads = systemThreads - 1;
|
myWorkerThreads = systemThreads - 1;
|
||||||
myTotalThreads = systemThreads;
|
myTotalThreads = systemThreads;
|
||||||
|
@ -306,15 +305,14 @@ void AtariNTSC::renderWithPhosphorThread(const uInt8* atari_in, const uInt32 in_
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
inline uInt32 AtariNTSC::getRGBPhosphor(const uInt32 c, const uInt32 p) const
|
inline uInt32 AtariNTSC::getRGBPhosphor(const uInt32 c, const uInt32 p) const
|
||||||
{
|
{
|
||||||
#define TO_RGB(color, red, green, blue) \
|
|
||||||
const uInt8 red = uInt8(color >> 16); \
|
|
||||||
const uInt8 green = uInt8(color >> 8);\
|
|
||||||
const uInt8 blue = uInt8(color);
|
|
||||||
|
|
||||||
TO_RGB(c, rc, gc, bc)
|
|
||||||
TO_RGB(p, rp, gp, bp)
|
|
||||||
|
|
||||||
// Mix current calculated frame with previous displayed frame
|
// Mix current calculated frame with previous displayed frame
|
||||||
|
const uInt8 rc = uInt8(c >> 16);
|
||||||
|
const uInt8 gc = uInt8(c >> 8);
|
||||||
|
const uInt8 bc = uInt8(c);
|
||||||
|
const uInt8 rp = uInt8(p >> 16);
|
||||||
|
const uInt8 gp = uInt8(p >> 8);
|
||||||
|
const uInt8 bp = uInt8(p);
|
||||||
|
|
||||||
const uInt8 rn = myPhosphorPalette[rc][rp];
|
const uInt8 rn = myPhosphorPalette[rc][rp];
|
||||||
const uInt8 gn = myPhosphorPalette[gc][gp];
|
const uInt8 gn = myPhosphorPalette[gc][gp];
|
||||||
const uInt8 bn = myPhosphorPalette[bc][bp];
|
const uInt8 bn = myPhosphorPalette[bc][bp];
|
||||||
|
@ -325,8 +323,8 @@ inline uInt32 AtariNTSC::getRGBPhosphor(const uInt32 c, const uInt32 p) const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void AtariNTSC::init(init_t& impl, const Setup& setup)
|
void AtariNTSC::init(init_t& impl, const Setup& setup)
|
||||||
{
|
{
|
||||||
impl.brightness = setup.brightness * (0.5f * rgb_unit) + rgb_offset;
|
impl.brightness = setup.brightness * (0.5F * rgb_unit) + rgb_offset;
|
||||||
impl.contrast = setup.contrast * (0.5f * rgb_unit) + rgb_unit;
|
impl.contrast = setup.contrast * (0.5F * rgb_unit) + rgb_unit;
|
||||||
|
|
||||||
impl.artifacts = setup.artifacts;
|
impl.artifacts = setup.artifacts;
|
||||||
if ( impl.artifacts > 0 )
|
if ( impl.artifacts > 0 )
|
||||||
|
@ -343,8 +341,8 @@ void AtariNTSC::init(init_t& impl, const Setup& setup)
|
||||||
/* generate gamma table */
|
/* generate gamma table */
|
||||||
if (true) /* was (gamma_size > 1) */
|
if (true) /* was (gamma_size > 1) */
|
||||||
{
|
{
|
||||||
float const to_float = 1.0f / (gamma_size - 1/*(gamma_size > 1)*/);
|
float const to_float = 1.F / (gamma_size - 1/*(gamma_size > 1)*/);
|
||||||
float const gamma = 1.1333f - setup.gamma * 0.5f;
|
float const gamma = 1.1333F - setup.gamma * 0.5F;
|
||||||
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
|
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
|
||||||
int i;
|
int i;
|
||||||
for ( i = 0; i < gamma_size; i++ )
|
for ( i = 0; i < gamma_size; i++ )
|
||||||
|
@ -360,13 +358,13 @@ void AtariNTSC::init(init_t& impl, const Setup& setup)
|
||||||
|
|
||||||
float s = sinf( hue ) * sat;
|
float s = sinf( hue ) * sat;
|
||||||
float c = cosf( hue ) * sat;
|
float c = cosf( hue ) * sat;
|
||||||
float* out = impl.to_rgb;
|
float* out = impl.to_rgb.data();
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = burst_count;
|
n = burst_count;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
float const* in = default_decoder;
|
float const* in = default_decoder.data();
|
||||||
int n2 = 3;
|
int n2 = 3;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -378,7 +376,7 @@ void AtariNTSC::init(init_t& impl, const Setup& setup)
|
||||||
while ( --n2 );
|
while ( --n2 );
|
||||||
#if 0 // burst_count is always 0
|
#if 0 // burst_count is always 0
|
||||||
if ( burst_count > 1 )
|
if ( burst_count > 1 )
|
||||||
ROTATE_IQ( s, c, 0.866025f, -0.5f ); /* +120 degrees */
|
ROTATE_IQ( s, c, 0.866025F, -0.5F ); /* +120 degrees */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
while ( --n );
|
while ( --n );
|
||||||
|
@ -388,18 +386,18 @@ void AtariNTSC::init(init_t& impl, const Setup& setup)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void AtariNTSC::initFilters(init_t& impl, const Setup& setup)
|
void AtariNTSC::initFilters(init_t& impl, const Setup& setup)
|
||||||
{
|
{
|
||||||
float kernels [kernel_size * 2];
|
std::array<float, kernel_size * 2> kernels;
|
||||||
|
|
||||||
/* generate luma (y) filter using sinc kernel */
|
/* generate luma (y) filter using sinc kernel */
|
||||||
{
|
{
|
||||||
/* sinc with rolloff (dsf) */
|
/* sinc with rolloff (dsf) */
|
||||||
float const rolloff = 1 + setup.sharpness * 0.032f;
|
float const rolloff = 1 + setup.sharpness * 0.032F;
|
||||||
constexpr float maxh = 32;
|
constexpr float maxh = 32;
|
||||||
float const pow_a_n = powf( rolloff, maxh );
|
float const pow_a_n = powf( rolloff, maxh );
|
||||||
float sum;
|
float sum;
|
||||||
/* quadratic mapping to reduce negative (blurring) range */
|
/* quadratic mapping to reduce negative (blurring) range */
|
||||||
float to_angle = setup.resolution + 1;
|
float to_angle = setup.resolution + 1;
|
||||||
to_angle = BSPF::PI_f / maxh * LUMA_CUTOFF * (to_angle * to_angle + 1.f);
|
to_angle = BSPF::PI_f / maxh * luma_cutoff * (to_angle * to_angle + 1.f);
|
||||||
|
|
||||||
kernels [kernel_size * 3 / 2] = maxh; /* default center value */
|
kernels [kernel_size * 3 / 2] = maxh; /* default center value */
|
||||||
for ( int i = 0; i < kernel_half * 2 + 1; i++ )
|
for ( int i = 0; i < kernel_half * 2 + 1; i++ )
|
||||||
|
@ -407,7 +405,7 @@ void AtariNTSC::initFilters(init_t& impl, const Setup& setup)
|
||||||
int x = i - kernel_half;
|
int x = i - kernel_half;
|
||||||
float angle = x * to_angle;
|
float angle = x * to_angle;
|
||||||
/* instability occurs at center point with rolloff very close to 1.0 */
|
/* instability occurs at center point with rolloff very close to 1.0 */
|
||||||
if ( x || pow_a_n > 1.056f || pow_a_n < 0.981f )
|
if ( x || pow_a_n > 1.056F || pow_a_n < 0.981F )
|
||||||
{
|
{
|
||||||
float rolloff_cos_a = rolloff * cosf( angle );
|
float rolloff_cos_a = rolloff * cosf( angle );
|
||||||
float num = 1 - rolloff_cos_a -
|
float num = 1 - rolloff_cos_a -
|
||||||
|
@ -415,7 +413,7 @@ void AtariNTSC::initFilters(init_t& impl, const Setup& setup)
|
||||||
pow_a_n * rolloff * cosf( (maxh - 1) * angle );
|
pow_a_n * rolloff * cosf( (maxh - 1) * angle );
|
||||||
float den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
|
float den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
|
||||||
float dsf = num / den;
|
float dsf = num / den;
|
||||||
kernels [kernel_size * 3 / 2 - kernel_half + i] = dsf - 0.5f;
|
kernels [kernel_size * 3 / 2 - kernel_half + i] = dsf - 0.5F;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,12 +422,12 @@ void AtariNTSC::initFilters(init_t& impl, const Setup& setup)
|
||||||
for ( int i = 0; i < kernel_half * 2 + 1; i++ )
|
for ( int i = 0; i < kernel_half * 2 + 1; i++ )
|
||||||
{
|
{
|
||||||
float x = BSPF::PI_f * 2 / (kernel_half * 2) * i;
|
float x = BSPF::PI_f * 2 / (kernel_half * 2) * i;
|
||||||
float blackman = 0.42f - 0.5f * cosf( x ) + 0.08f * cosf( x * 2 );
|
float blackman = 0.42F - 0.5F * cosf( x ) + 0.08F * cosf( x * 2 );
|
||||||
sum += (kernels [kernel_size * 3 / 2 - kernel_half + i] *= blackman);
|
sum += (kernels [kernel_size * 3 / 2 - kernel_half + i] *= blackman);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* normalize kernel */
|
/* normalize kernel */
|
||||||
sum = 1.0f / sum;
|
sum = 1.0F / sum;
|
||||||
for ( int i = 0; i < kernel_half * 2 + 1; i++ )
|
for ( int i = 0; i < kernel_half * 2 + 1; i++ )
|
||||||
{
|
{
|
||||||
int x = kernel_size * 3 / 2 - kernel_half + i;
|
int x = kernel_size * 3 / 2 - kernel_half + i;
|
||||||
|
@ -439,7 +437,7 @@ void AtariNTSC::initFilters(init_t& impl, const Setup& setup)
|
||||||
|
|
||||||
/* generate chroma (iq) filter using gaussian kernel */
|
/* generate chroma (iq) filter using gaussian kernel */
|
||||||
{
|
{
|
||||||
constexpr float cutoff_factor = -0.03125f;
|
constexpr float cutoff_factor = -0.03125F;
|
||||||
float cutoff = setup.bleed;
|
float cutoff = setup.bleed;
|
||||||
|
|
||||||
if ( cutoff < 0 )
|
if ( cutoff < 0 )
|
||||||
|
@ -448,9 +446,9 @@ void AtariNTSC::initFilters(init_t& impl, const Setup& setup)
|
||||||
cutoff *= cutoff;
|
cutoff *= cutoff;
|
||||||
cutoff *= cutoff;
|
cutoff *= cutoff;
|
||||||
cutoff *= cutoff;
|
cutoff *= cutoff;
|
||||||
cutoff *= -30.0f / 0.65f;
|
cutoff *= -30.0F / 0.65F;
|
||||||
}
|
}
|
||||||
cutoff = cutoff_factor - 0.65f * cutoff_factor * cutoff;
|
cutoff = cutoff_factor - 0.65F * cutoff_factor * cutoff;
|
||||||
|
|
||||||
for ( int i = -kernel_half; i <= kernel_half; i++ )
|
for ( int i = -kernel_half; i <= kernel_half; i++ )
|
||||||
kernels [kernel_size / 2 + i] = expf( i * i * cutoff );
|
kernels [kernel_size / 2 + i] = expf( i * i * cutoff );
|
||||||
|
@ -463,7 +461,7 @@ void AtariNTSC::initFilters(init_t& impl, const Setup& setup)
|
||||||
for ( x = i; x < kernel_size; x += 2 )
|
for ( x = i; x < kernel_size; x += 2 )
|
||||||
sum += kernels [x];
|
sum += kernels [x];
|
||||||
|
|
||||||
sum = 1.0f / sum;
|
sum = 1.0F / sum;
|
||||||
for ( x = i; x < kernel_size; x += 2 )
|
for ( x = i; x < kernel_size; x += 2 )
|
||||||
{
|
{
|
||||||
kernels [x] *= sum;
|
kernels [x] *= sum;
|
||||||
|
@ -472,13 +470,13 @@ void AtariNTSC::initFilters(init_t& impl, const Setup& setup)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate linear rescale kernels */
|
/* generate linear rescale kernels */
|
||||||
float weight = 1.0f;
|
float weight = 1.0F;
|
||||||
float* out = impl.kernel;
|
float* out = impl.kernel.data();
|
||||||
int n = rescale_out;
|
int n = rescale_out;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
float remain = 0;
|
float remain = 0;
|
||||||
weight -= 1.0f / rescale_in;
|
weight -= 1.0F / rescale_in;
|
||||||
for ( int i = 0; i < kernel_size * 2; i++ )
|
for ( int i = 0; i < kernel_size * 2; i++ )
|
||||||
{
|
{
|
||||||
float cur = kernels [i];
|
float cur = kernels [i];
|
||||||
|
@ -495,7 +493,7 @@ void AtariNTSC::initFilters(init_t& impl, const Setup& setup)
|
||||||
void AtariNTSC::genKernel(init_t& impl, float y, float i, float q, uInt32* out)
|
void AtariNTSC::genKernel(init_t& impl, float y, float i, float q, uInt32* out)
|
||||||
{
|
{
|
||||||
/* generate for each scanline burst phase */
|
/* generate for each scanline burst phase */
|
||||||
float const* to_rgb = impl.to_rgb;
|
float const* to_rgb = impl.to_rgb.data();
|
||||||
int burst_remain = burst_count;
|
int burst_remain = burst_count;
|
||||||
y -= rgb_offset;
|
y -= rgb_offset;
|
||||||
do
|
do
|
||||||
|
@ -504,7 +502,7 @@ void AtariNTSC::genKernel(init_t& impl, float y, float i, float q, uInt32* out)
|
||||||
Convolve these with kernels which: filter respective components, apply
|
Convolve these with kernels which: filter respective components, apply
|
||||||
sharpening, and rescale horizontally. Convert resulting yiq to rgb and pack
|
sharpening, and rescale horizontally. Convert resulting yiq to rgb and pack
|
||||||
into integer. Based on algorithm by NewRisingSun. */
|
into integer. Based on algorithm by NewRisingSun. */
|
||||||
pixel_info_t const* pixel = atari_ntsc_pixels;
|
pixel_info_t const* pixel = atari_ntsc_pixels.data();
|
||||||
int alignment_remain = alignment_count;
|
int alignment_remain = alignment_count;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -538,7 +536,7 @@ void AtariNTSC::genKernel(init_t& impl, float y, float i, float q, uInt32* out)
|
||||||
else
|
else
|
||||||
k -= kernel_size * 2 * (rescale_out - 1) + 2;
|
k -= kernel_size * 2 * (rescale_out - 1) + 2;
|
||||||
{
|
{
|
||||||
int r, g, b = YIQ_TO_RGB( fy, fi, fq, to_rgb, int, r, g );
|
int r, g, b; YIQ_TO_RGB( fy, fi, fq, to_rgb, r, g, b );
|
||||||
*out++ = PACK_RGB( r, g, b ) - rgb_bias;
|
*out++ = PACK_RGB( r, g, b ) - rgb_bias;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -550,24 +548,26 @@ void AtariNTSC::genKernel(init_t& impl, float y, float i, float q, uInt32* out)
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
const AtariNTSC::Setup AtariNTSC::TV_Composite = {
|
const AtariNTSC::Setup AtariNTSC::TV_Composite = {
|
||||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.15f, 0.0f, 0.0f, 0.0f
|
0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.15F, 0.0F, 0.0F, 0.0F
|
||||||
};
|
};
|
||||||
const AtariNTSC::Setup AtariNTSC::TV_SVideo = {
|
const AtariNTSC::Setup AtariNTSC::TV_SVideo = {
|
||||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.45f, -1.0f, -1.0f, 0.0f
|
0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.45F, -1.0F, -1.0F, 0.0F
|
||||||
};
|
};
|
||||||
const AtariNTSC::Setup AtariNTSC::TV_RGB = {
|
const AtariNTSC::Setup AtariNTSC::TV_RGB = {
|
||||||
0.0f, 0.0f, 0.0f, 0.0f, 0.2f, 0.0f, 0.70f, -1.0f, -1.0f, -1.0f
|
0.0F, 0.0F, 0.0F, 0.0F, 0.2F, 0.0F, 0.70F, -1.0F, -1.0F, -1.0F
|
||||||
};
|
};
|
||||||
const AtariNTSC::Setup AtariNTSC::TV_Bad = {
|
const AtariNTSC::Setup AtariNTSC::TV_Bad = {
|
||||||
0.1f, -0.3f, 0.3f, 0.25f, 0.2f, 0.0f, 0.1f, 0.5f, 0.5f, 0.5f
|
0.1F, -0.3F, 0.3F, 0.25F, 0.2F, 0.0F, 0.1F, 0.5F, 0.5F, 0.5F
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
const AtariNTSC::pixel_info_t AtariNTSC::atari_ntsc_pixels[alignment_count] = {
|
const std::array<AtariNTSC::pixel_info_t, AtariNTSC::alignment_count>
|
||||||
{ PIXEL_OFFSET( -4, -9 ), { 1, 1, 1, 1 } },
|
AtariNTSC::atari_ntsc_pixels = { {
|
||||||
{ PIXEL_OFFSET( 0, -5 ), { 1, 1, 1, 1 } },
|
{ PIXEL_OFFSET1(-4, -9), PIXEL_OFFSET2(-4), { 1, 1, 1, 1 } },
|
||||||
};
|
{ PIXEL_OFFSET1( 0, -5), PIXEL_OFFSET2( 0), { 1, 1, 1, 1 } }
|
||||||
|
} };
|
||||||
|
|
||||||
const float AtariNTSC::default_decoder[6] = {
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
0.9563f, 0.6210f, -0.2721f, -0.6474f, -1.1070f, 1.7046f
|
const std::array<float, 6> AtariNTSC::default_decoder = {
|
||||||
|
0.9563F, 0.6210F, -0.2721F, -0.6474F, -1.1070F, 1.7046F
|
||||||
};
|
};
|
||||||
|
|
|
@ -151,16 +151,20 @@ class AtariNTSC
|
||||||
rgb_bias = rgb_unit * 2 * rgb_builder,
|
rgb_bias = rgb_unit * 2 * rgb_builder,
|
||||||
|
|
||||||
std_decoder_hue = 0,
|
std_decoder_hue = 0,
|
||||||
ext_decoder_hue = std_decoder_hue + 15
|
ext_decoder_hue = std_decoder_hue + 15,
|
||||||
|
|
||||||
|
atari_ntsc_clamp_mask = rgb_builder * 3 / 2,
|
||||||
|
atari_ntsc_clamp_add = rgb_builder * 0x101
|
||||||
;
|
;
|
||||||
|
|
||||||
#define artifacts_mid 1.5f
|
static constexpr float
|
||||||
#define artifacts_max 2.5f
|
artifacts_mid = 1.5F,
|
||||||
#define fringing_mid 1.0f
|
artifacts_max = 2.5F,
|
||||||
#define fringing_max 2.0f
|
fringing_mid = 1.0F,
|
||||||
#define rgb_offset (rgb_unit * 2 + 0.5f)
|
fringing_max = 2.0F,
|
||||||
|
rgb_offset = (rgb_unit * 2 + 0.5F),
|
||||||
#define LUMA_CUTOFF 0.20f
|
luma_cutoff = 0.20F
|
||||||
|
;
|
||||||
|
|
||||||
uInt32 myColorTable[palette_size][entry_size];
|
uInt32 myColorTable[palette_size][entry_size];
|
||||||
uInt8 myPhosphorPalette[256][256];
|
uInt8 myPhosphorPalette[256][256];
|
||||||
|
@ -172,18 +176,18 @@ class AtariNTSC
|
||||||
|
|
||||||
struct init_t
|
struct init_t
|
||||||
{
|
{
|
||||||
float to_rgb [burst_count * 6];
|
std::array<float, burst_count * 6> to_rgb;
|
||||||
float to_float [gamma_size];
|
std::array<float, gamma_size> to_float;
|
||||||
float contrast;
|
float contrast;
|
||||||
float brightness;
|
float brightness;
|
||||||
float artifacts;
|
float artifacts;
|
||||||
float fringing;
|
float fringing;
|
||||||
float kernel [rescale_out * kernel_size * 2];
|
std::array<float, rescale_out * kernel_size * 2> kernel;
|
||||||
|
|
||||||
init_t() : contrast(0.0), brightness(0.0), artifacts(0.0), fringing(0.0) {
|
init_t() : contrast(0.0), brightness(0.0), artifacts(0.0), fringing(0.0) {
|
||||||
std::fill(to_rgb, to_rgb + burst_count * 6, 0.0);
|
to_rgb.fill(0.0);
|
||||||
std::fill(to_float, to_float + gamma_size, 0.0);
|
to_float.fill(0.0);
|
||||||
std::fill(kernel, kernel + rescale_out * kernel_size * 2, 0.0);
|
kernel.fill(0.0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
init_t myImpl;
|
init_t myImpl;
|
||||||
|
@ -192,11 +196,11 @@ class AtariNTSC
|
||||||
{
|
{
|
||||||
int offset;
|
int offset;
|
||||||
float negate;
|
float negate;
|
||||||
float kernel [4];
|
std::array<float, 4> kernel;
|
||||||
};
|
};
|
||||||
static const pixel_info_t atari_ntsc_pixels[alignment_count];
|
static const std::array<pixel_info_t, alignment_count> atari_ntsc_pixels;
|
||||||
|
|
||||||
static const float default_decoder[6];
|
static const std::array<float, 6> default_decoder;
|
||||||
|
|
||||||
void init(init_t& impl, const Setup& setup);
|
void init(init_t& impl, const Setup& setup);
|
||||||
void initFilters(init_t& impl, const Setup& setup);
|
void initFilters(init_t& impl, const Setup& setup);
|
||||||
|
@ -220,57 +224,60 @@ class AtariNTSC
|
||||||
kernel##index = (color_ = (color), myColorTable[color_]);\
|
kernel##index = (color_ = (color), myColorTable[color_]);\
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates output in the specified 32-bit format (x = junk bits).
|
// Generates output in the specified 32-bit format.
|
||||||
// native: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format)
|
|
||||||
// 8888: 00000000 RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8-8 32-bit ARGB)
|
// 8888: 00000000 RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8-8 32-bit ARGB)
|
||||||
#define ATARI_NTSC_RGB_OUT_8888( index, rgb_out ) {\
|
#define ATARI_NTSC_RGB_OUT_8888( index, rgb_out ) {\
|
||||||
uInt32 raw_ =\
|
uInt32 raw_ =\
|
||||||
kernel0 [index ] + kernel1 [(index+10)%7+14] +\
|
kernel0 [index ] + kernel1 [(index+10)%7+14] +\
|
||||||
kernelx0 [(index+7)%14] + kernelx1 [(index+ 3)%7+14+7];\
|
kernelx0 [(index+7)%14] + kernelx1 [(index+ 3)%7+14+7];\
|
||||||
ATARI_NTSC_CLAMP_( raw_, 0 );\
|
ATARI_NTSC_CLAMP( raw_, 0 );\
|
||||||
rgb_out = (raw_>>5 & 0x00FF0000)|(raw_>>3 & 0x0000FF00)|(raw_>>1 & 0x000000FF);\
|
rgb_out = (raw_>>5 & 0x00FF0000)|(raw_>>3 & 0x0000FF00)|(raw_>>1 & 0x000000FF);\
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common ntsc macros
|
// Common ntsc macros
|
||||||
#define atari_ntsc_clamp_mask (rgb_builder * 3 / 2)
|
static inline constexpr void ATARI_NTSC_CLAMP( uInt32& io, uInt32 shift ) {
|
||||||
#define atari_ntsc_clamp_add (rgb_builder * 0x101)
|
uInt32 sub = io >> (9-(shift)) & atari_ntsc_clamp_mask;
|
||||||
#define ATARI_NTSC_CLAMP_( io, shift ) {\
|
uInt32 clamp = atari_ntsc_clamp_add - sub;
|
||||||
uInt32 sub = (io) >> (9-(shift)) & atari_ntsc_clamp_mask;\
|
io |= clamp;
|
||||||
uInt32 clamp = atari_ntsc_clamp_add - sub;\
|
clamp -= sub;
|
||||||
io |= clamp;\
|
io &= clamp;
|
||||||
clamp -= sub;\
|
|
||||||
io &= clamp;\
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kernel generation
|
static inline constexpr void RGB_TO_YIQ(float r, float g, float b,
|
||||||
|
float& y, float& i, float& q) {
|
||||||
|
y = r * 0.299F + g * 0.587F + b * 0.114F;
|
||||||
|
i = r * 0.595716F - g * 0.274453F - b * 0.321263F;
|
||||||
|
q = r * 0.211456F - g * 0.522591F + b * 0.311135F;
|
||||||
|
}
|
||||||
|
static inline constexpr void YIQ_TO_RGB(float y, float i, float q,
|
||||||
|
const float* to_rgb, int& ir, int& ig, int& ib) {
|
||||||
|
ir = static_cast<int>(y + to_rgb[0] * i + to_rgb[1] * q);
|
||||||
|
ig = static_cast<int>(y + to_rgb[2] * i + to_rgb[3] * q);
|
||||||
|
ib = static_cast<int>(y + to_rgb[4] * i + to_rgb[5] * q);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline constexpr uInt32 PACK_RGB( int r, int g, int b ) {
|
||||||
|
return r << 21 | g << 11 | b << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converted from C-style macros; I don't even pretend to understand the logic here :)
|
||||||
|
static inline constexpr int PIXEL_OFFSET1( int ntsc, int scaled ) {
|
||||||
|
return (kernel_size / 2 + ((ntsc) - (scaled) / rescale_out * rescale_in) +
|
||||||
|
((((scaled) + rescale_out * 10) % rescale_out) != 0) +
|
||||||
|
(rescale_out - (((scaled) + rescale_out * 10) % rescale_out)) % rescale_out +
|
||||||
|
(kernel_size * 2 * (((scaled) + rescale_out * 10) % rescale_out)));
|
||||||
|
}
|
||||||
|
static inline constexpr int PIXEL_OFFSET2( int ntsc ) {
|
||||||
|
return 1.0F - (((ntsc) + 100) & 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 // DEAD CODE
|
||||||
#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;\
|
||||||
q = i * sin_b + q * cos_b;\
|
q = i * sin_b + q * cos_b;\
|
||||||
i = t;\
|
i = t;\
|
||||||
}
|
}
|
||||||
#define RGB_TO_YIQ( r, g, b, y, i ) (\
|
|
||||||
(y = (r) * 0.299f + (g) * 0.587f + (b) * 0.114f),\
|
|
||||||
(i = (r) * 0.595716f - (g) * 0.274453f - (b) * 0.321263f),\
|
|
||||||
((r) * 0.211456f - (g) * 0.522591f + (b) * 0.311135f)\
|
|
||||||
)
|
|
||||||
#define YIQ_TO_RGB( y, i, q, to_rgb, type, r, g ) (\
|
|
||||||
r = type(y + to_rgb [0] * i + to_rgb [1] * q),\
|
|
||||||
g = type(y + to_rgb [2] * i + to_rgb [3] * q),\
|
|
||||||
type(y + to_rgb [4] * i + to_rgb [5] * q)\
|
|
||||||
)
|
|
||||||
#ifndef PACK_RGB
|
|
||||||
#define PACK_RGB( r, g, b ) ((r) << 21 | (g) << 11 | (b) << 1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define PIXEL_OFFSET_( ntsc, scaled ) \
|
|
||||||
(kernel_size / 2 + ntsc + (scaled != 0) + (rescale_out - scaled) % rescale_out + \
|
|
||||||
(kernel_size * 2 * scaled))
|
|
||||||
|
|
||||||
#define PIXEL_OFFSET( ntsc, scaled ) \
|
|
||||||
PIXEL_OFFSET_( ((ntsc) - (scaled) / rescale_out * rescale_in),\
|
|
||||||
(((scaled) + rescale_out * 10) % rescale_out) ),\
|
|
||||||
(1.0f - (((ntsc) + 100) & 2))
|
|
||||||
|
|
||||||
#define DISTRIBUTE_ERROR( a, b, c ) {\
|
#define DISTRIBUTE_ERROR( a, b, c ) {\
|
||||||
uInt32 fourth = (error + 2 * rgb_builder) >> 2;\
|
uInt32 fourth = (error + 2 * rgb_builder) >> 2;\
|
||||||
|
@ -285,11 +292,12 @@ class AtariNTSC
|
||||||
#define RGB_PALETTE_OUT( rgb, out_ ) {\
|
#define RGB_PALETTE_OUT( rgb, out_ ) {\
|
||||||
unsigned char* out = (out_);\
|
unsigned char* out = (out_);\
|
||||||
uInt32 clamped = (rgb);\
|
uInt32 clamped = (rgb);\
|
||||||
ATARI_NTSC_CLAMP_( clamped, (8 - rgb_bits) );\
|
ATARI_NTSC_CLAMP( clamped, (8 - rgb_bits) );\
|
||||||
out [0] = (unsigned char) (clamped >> 21);\
|
out [0] = (unsigned char) (clamped >> 21);\
|
||||||
out [1] = (unsigned char) (clamped >> 11);\
|
out [1] = (unsigned char) (clamped >> 11);\
|
||||||
out [2] = (unsigned char) (clamped >> 1);\
|
out [2] = (unsigned char) (clamped >> 1);\
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -232,7 +232,7 @@ void NTSCFilter::convertToAdjustable(Adjustable& adjustable,
|
||||||
AtariNTSC::Setup NTSCFilter::myCustomSetup = AtariNTSC::TV_Composite;
|
AtariNTSC::Setup NTSCFilter::myCustomSetup = AtariNTSC::TV_Composite;
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
const NTSCFilter::AdjustableTag NTSCFilter::ourCustomAdjustables[10] = {
|
const std::array<NTSCFilter::AdjustableTag, 10> NTSCFilter::ourCustomAdjustables = { {
|
||||||
{ "contrast", &myCustomSetup.contrast },
|
{ "contrast", &myCustomSetup.contrast },
|
||||||
{ "brightness", &myCustomSetup.brightness },
|
{ "brightness", &myCustomSetup.brightness },
|
||||||
{ "hue", &myCustomSetup.hue },
|
{ "hue", &myCustomSetup.hue },
|
||||||
|
@ -243,4 +243,4 @@ const NTSCFilter::AdjustableTag NTSCFilter::ourCustomAdjustables[10] = {
|
||||||
{ "artifacts", &myCustomSetup.artifacts },
|
{ "artifacts", &myCustomSetup.artifacts },
|
||||||
{ "fringing", &myCustomSetup.fringing },
|
{ "fringing", &myCustomSetup.fringing },
|
||||||
{ "bleeding", &myCustomSetup.bleed }
|
{ "bleeding", &myCustomSetup.bleed }
|
||||||
};
|
} };
|
||||||
|
|
|
@ -109,12 +109,12 @@ class NTSCFilter
|
||||||
|
|
||||||
// Perform Blargg filtering on input buffer, place results in
|
// Perform Blargg filtering on input buffer, place results in
|
||||||
// output buffer
|
// output buffer
|
||||||
inline void render(uInt8* src_buf, uInt32 src_width, uInt32 src_height,
|
inline void render(const uInt8* src_buf, uInt32 src_width, uInt32 src_height,
|
||||||
uInt32* dest_buf, uInt32 dest_pitch)
|
uInt32* dest_buf, uInt32 dest_pitch)
|
||||||
{
|
{
|
||||||
myNTSC.render(src_buf, src_width, src_height, dest_buf, dest_pitch);
|
myNTSC.render(src_buf, src_width, src_height, dest_buf, dest_pitch);
|
||||||
}
|
}
|
||||||
inline void render(uInt8* src_buf, uInt32 src_width, uInt32 src_height,
|
inline void render(const uInt8* src_buf, uInt32 src_width, uInt32 src_height,
|
||||||
uInt32* dest_buf, uInt32 dest_pitch, uInt32* prev_buf)
|
uInt32* dest_buf, uInt32 dest_pitch, uInt32* prev_buf)
|
||||||
{
|
{
|
||||||
myNTSC.render(src_buf, src_width, src_height, dest_buf, dest_pitch, prev_buf);
|
myNTSC.render(src_buf, src_width, src_height, dest_buf, dest_pitch, prev_buf);
|
||||||
|
@ -156,7 +156,7 @@ class NTSCFilter
|
||||||
float* value;
|
float* value;
|
||||||
};
|
};
|
||||||
uInt32 myCurrentAdjustable;
|
uInt32 myCurrentAdjustable;
|
||||||
static const AdjustableTag ourCustomAdjustables[10];
|
static const std::array<AdjustableTag, 10> ourCustomAdjustables;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
Loading…
Reference in New Issue