From bd78683274add8c0215378d855365cc1392fb693 Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Fri, 30 Jun 2017 14:10:14 -0230 Subject: [PATCH] Rearranged some Blargg code, added comments, general cleanups. For now, Blargg phosphor mode simply shows the same image as without phosphor. This is a WIP, and if we can't get it finished for 5.0, it will be released as-is. Phosphor blend now defaults to 0 in the base properties, and is converted to 50 before being passed to higher levels. This needs to change when we get to issue #144. --- src/common/tv_filters/AtariNTSC.cxx | 73 ++--------------------- src/common/tv_filters/AtariNTSC.hxx | 65 ++++++++++----------- src/common/tv_filters/NTSCFilter.cxx | 42 +------------- src/common/tv_filters/NTSCFilter.hxx | 26 ++++----- src/emucore/Props.cxx | 15 +++-- src/emucore/TIASurface.cxx | 87 ++++++++++++++-------------- src/emucore/TIASurface.hxx | 27 +++++---- src/emucore/tia/TIA.cxx | 23 +++----- src/emucore/tia/TIA.hxx | 12 ++-- src/tools/PropSet.pm | 2 +- 10 files changed, 138 insertions(+), 234 deletions(-) diff --git a/src/common/tv_filters/AtariNTSC.cxx b/src/common/tv_filters/AtariNTSC.cxx index b3fa1e184..fc384c059 100644 --- a/src/common/tv_filters/AtariNTSC.cxx +++ b/src/common/tv_filters/AtariNTSC.cxx @@ -69,24 +69,24 @@ void AtariNTSC::initializePalette(const uInt8* palette) void AtariNTSC::blitSingle(const uInt8* atari_in, uInt32 in_width, uInt32 in_height, void* rgb_out, uInt32 out_pitch) { - uInt32 const chunk_count = (in_width - 1) / AN_in_chunk; + uInt32 const chunk_count = (in_width - 1) / PIXEL_in_chunk; while ( in_height-- ) { const uInt8* line_in = atari_in; - ATARI_NTSC_BEGIN_ROW( &myNTSC, AN_black, line_in[0] ); + ATARI_NTSC_BEGIN_ROW( NTSC_black, line_in[0] ); uInt32* restrict line_out = static_cast(rgb_out); ++line_in; for ( uInt32 n = chunk_count; n; --n ) { /* order of input and output pixels must not be altered */ - ATARI_NTSC_COLOR_IN( 0, &myNTSC, line_in[0] ); + ATARI_NTSC_COLOR_IN( 0, line_in[0] ); ATARI_NTSC_RGB_OUT_8888( 0, line_out[0] ); ATARI_NTSC_RGB_OUT_8888( 1, line_out[1] ); ATARI_NTSC_RGB_OUT_8888( 2, line_out[2] ); ATARI_NTSC_RGB_OUT_8888( 3, line_out[3] ); - ATARI_NTSC_COLOR_IN( 1, &myNTSC, line_in[1] ); + ATARI_NTSC_COLOR_IN( 1, line_in[1] ); ATARI_NTSC_RGB_OUT_8888( 4, line_out[4] ); ATARI_NTSC_RGB_OUT_8888( 5, line_out[5] ); ATARI_NTSC_RGB_OUT_8888( 6, line_out[6] ); @@ -96,13 +96,13 @@ void AtariNTSC::blitSingle(const uInt8* atari_in, uInt32 in_width, } /* finish final pixels */ - ATARI_NTSC_COLOR_IN( 0, &myNTSC, AN_black ); + ATARI_NTSC_COLOR_IN( 0, NTSC_black ); ATARI_NTSC_RGB_OUT_8888( 0, line_out[0] ); ATARI_NTSC_RGB_OUT_8888( 1, line_out[1] ); ATARI_NTSC_RGB_OUT_8888( 2, line_out[2] ); ATARI_NTSC_RGB_OUT_8888( 3, line_out[3] ); - ATARI_NTSC_COLOR_IN( 1, &myNTSC, AN_black ); + ATARI_NTSC_COLOR_IN( 1, NTSC_black ); ATARI_NTSC_RGB_OUT_8888( 4, line_out[4] ); ATARI_NTSC_RGB_OUT_8888( 5, line_out[5] ); ATARI_NTSC_RGB_OUT_8888( 6, line_out[6] ); @@ -112,67 +112,6 @@ void AtariNTSC::blitSingle(const uInt8* atari_in, uInt32 in_width, } } -#if 0 -void atari_ntsc_blit_double( atari_ntsc_t const* ntsc, - atari_ntsc_in_t const* atari_in1, atari_ntsc_in_t const* atari_in2, - uInt32 in_width, uInt32 in_height, void* rgb_out, uInt32 out_pitch ) -{ - #define TO_DOUBLE(pixel1, pixel2) (((pixel1>>1)<<7)+(pixel2>>1)) - - uInt32 const chunk_count = (in_width - 1) / atari_ntsc_in_chunk; - while ( in_height-- ) - { - atari_ntsc_in_t const* line_in1 = atari_in1; - atari_ntsc_in_t const* line_in2 = atari_in2; - ATARI_NTSC_BEGIN_ROW( ntsc, - TO_DOUBLE(atari_ntsc_black, atari_ntsc_black), - TO_DOUBLE(line_in1[0], line_in2[0]) ); - uInt32* restrict line_out = static_cast(rgb_out); - ++line_in1; - ++line_in2; - - for ( uInt32 n = chunk_count; n; --n ) - { - /* order of input and output pixels must not be altered */ - ATARI_NTSC_COLOR_IN( 0, ntsc, - TO_DOUBLE(line_in1[0], line_in2[0]) ); - ATARI_NTSC_RGB_OUT_8888( 0, line_out[0] ); - ATARI_NTSC_RGB_OUT_8888( 1, line_out[1] ); - ATARI_NTSC_RGB_OUT_8888( 2, line_out[2] ); - ATARI_NTSC_RGB_OUT_8888( 3, line_out[3] ); - - ATARI_NTSC_COLOR_IN( 1, ntsc, - TO_DOUBLE(line_in1[1], line_in2[1]) ); - ATARI_NTSC_RGB_OUT_8888( 4, line_out[4] ); - ATARI_NTSC_RGB_OUT_8888( 5, line_out[5] ); - ATARI_NTSC_RGB_OUT_8888( 6, line_out[6] ); - - line_in1 += 2; - line_in2 += 2; - line_out += 7; - } - - /* finish final pixels */ - ATARI_NTSC_COLOR_IN( 0, ntsc, - TO_DOUBLE(atari_ntsc_black, atari_ntsc_black) ); - ATARI_NTSC_RGB_OUT_8888( 0, line_out[0] ); - ATARI_NTSC_RGB_OUT_8888( 1, line_out[1] ); - ATARI_NTSC_RGB_OUT_8888( 2, line_out[2] ); - ATARI_NTSC_RGB_OUT_8888( 3, line_out[3] ); - - ATARI_NTSC_COLOR_IN( 1, ntsc, - TO_DOUBLE(atari_ntsc_black, atari_ntsc_black) ); - ATARI_NTSC_RGB_OUT_8888( 4, line_out[4] ); - ATARI_NTSC_RGB_OUT_8888( 5, line_out[5] ); - ATARI_NTSC_RGB_OUT_8888( 6, line_out[6] ); - - atari_in1 += in_width; - atari_in2 += in_width; - rgb_out = static_cast(rgb_out) + out_pitch; - } -} -#endif - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void AtariNTSC::init(init_t& impl, const Setup& setup) { diff --git a/src/common/tv_filters/AtariNTSC.hxx b/src/common/tv_filters/AtariNTSC.hxx index 76b4be0a6..ae5510f13 100644 --- a/src/common/tv_filters/AtariNTSC.hxx +++ b/src/common/tv_filters/AtariNTSC.hxx @@ -31,6 +31,12 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +/** + The class is basically a thin wrapper around atari_ntsc_xxx structs + and methods, so that the rest of the codebase isn't affected by + updated versions of Blargg code. +*/ + #ifndef ATARI_NTSC_HXX #define ATARI_NTSC_HXX @@ -82,25 +88,25 @@ class AtariNTSC void blitSingle(const uInt8* atari_in, uInt32 in_width, uInt32 in_height, void* rgb_out, uInt32 out_pitch); - // Number of output pixels written by blitter for given input width. - // Width might be rounded down slightly; use inWidth() on result to - // find rounded value. Guaranteed not to round 160 down at all. - static uInt32 outWidth(uInt32 in_width) { - return ((((in_width) - 1) / AN_in_chunk + 1)* AN_out_chunk); - } - // 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 uInt32 inWidth( uInt32 out_width ) { - return (((out_width) / AN_out_chunk - 1) * AN_in_chunk + 1); + return (((out_width) / PIXEL_out_chunk - 1) * PIXEL_in_chunk + 1); + } + + // Number of output pixels written by blitter for given input width. + // Width might be rounded down slightly; use inWidth() on result to + // find rounded value. Guaranteed not to round 160 down at all. + static uInt32 outWidth(uInt32 in_width) { + return ((((in_width) - 1) / PIXEL_in_chunk + 1)* PIXEL_out_chunk); } private: enum { - AN_in_chunk = 2, // number of input pixels read per chunk - AN_out_chunk = 7, // number of output pixels generated per chunk - AN_black = 0, // palette index for black + PIXEL_in_chunk = 2, // number of input pixels read per chunk + PIXEL_out_chunk = 7, // number of output pixels generated per chunk + NTSC_black = 0, // palette index for black alignment_count = 2, burst_count = 1, @@ -166,12 +172,20 @@ class AtariNTSC // Begins outputting row and starts two pixels. First pixel will be cut // off a bit. Use atari_ntsc_black for unused pixels. - #define ATARI_NTSC_BEGIN_ROW( ntsc, pixel0, pixel1 ) \ - ATARI_NTSC_BEGIN_ROW_6_( pixel0, pixel1, ATARI_NTSC_ENTRY_, ntsc ) + #define ATARI_NTSC_BEGIN_ROW( pixel0, pixel1 ) \ + unsigned const atari_ntsc_pixel0_ = (pixel0);\ + uInt32 const* kernel0 = myNTSC.table[atari_ntsc_pixel0_];\ + unsigned const atari_ntsc_pixel1_ = (pixel1);\ + uInt32 const* kernel1 = myNTSC.table[atari_ntsc_pixel1_];\ + uInt32 const* kernelx0;\ + uInt32 const* kernelx1 = kernel0 // Begins input pixel - #define ATARI_NTSC_COLOR_IN( in_index, ntsc, color_in ) \ - ATARI_NTSC_COLOR_IN_( in_index, color_in, ATARI_NTSC_ENTRY_, ntsc ) + #define ATARI_NTSC_COLOR_IN( index, color ) {\ + unsigned color_;\ + kernelx##index = kernel##index;\ + kernel##index = (color_ = (color), myNTSC.table[color_]);\ + } // Generates output in the specified 32-bit format (x = junk bits). // native: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format) @@ -184,18 +198,7 @@ class AtariNTSC rgb_out = (raw_>>5 & 0x00FF0000)|(raw_>>3 & 0x0000FF00)|(raw_>>1 & 0x000000FF);\ } - #define ATARI_NTSC_ENTRY_( ntsc, n ) (ntsc)->table [n] - - // common 3->7 ntsc macros - #define ATARI_NTSC_BEGIN_ROW_6_( pixel0, pixel1, ENTRY, table ) \ - unsigned const atari_ntsc_pixel0_ = (pixel0);\ - uInt32 const* kernel0 = ENTRY( table, atari_ntsc_pixel0_ );\ - unsigned const atari_ntsc_pixel1_ = (pixel1);\ - uInt32 const* kernel1 = ENTRY( table, atari_ntsc_pixel1_ );\ - uInt32 const* kernelx0;\ - uInt32 const* kernelx1 = kernel0 - - // common ntsc macros + // Common ntsc macros #define atari_ntsc_clamp_mask (rgb_builder * 3 / 2) #define atari_ntsc_clamp_add (rgb_builder * 0x101) #define ATARI_NTSC_CLAMP_( io, shift ) {\ @@ -206,13 +209,7 @@ class AtariNTSC io &= clamp;\ } - #define ATARI_NTSC_COLOR_IN_( index, color, ENTRY, table ) {\ - unsigned color_;\ - kernelx##index = kernel##index;\ - kernel##index = (color_ = (color), ENTRY( table, color_ ));\ - } - - // kernel generation + // Kernel generation #define ROTATE_IQ( i, q, sin_b, cos_b ) {\ float t;\ t = i * cos_b - q * sin_b;\ diff --git a/src/common/tv_filters/NTSCFilter.cxx b/src/common/tv_filters/NTSCFilter.cxx index 8e984adab..95b7d63f3 100644 --- a/src/common/tv_filters/NTSCFilter.cxx +++ b/src/common/tv_filters/NTSCFilter.cxx @@ -28,46 +28,6 @@ NTSCFilter::NTSCFilter() { } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void NTSCFilter::setTIAPalette(const TIASurface& tiaSurface, const uInt32* palette) -{ - // Normal TIA palette contains 256 colours, where every odd indexed colour - // is used for PAL colour-loss effect - // This can't be emulated here, since the memory requirements would be too - // great (a 4x increase) - // Therefore, we need to skip every second index, since the array passed to - // the Blargg code assumes 128 colours - uInt8* ptr = myTIAPalette; - -#if 0 - // Set palette for phosphor effect - for(int i = 0; i < 256; i+=2) - { - for(int j = 0; j < 256; j+=2) - { - uInt8 ri = (palette[i] >> 16) & 0xff; - uInt8 gi = (palette[i] >> 8) & 0xff; - uInt8 bi = palette[i] & 0xff; - uInt8 rj = (palette[j] >> 16) & 0xff; - uInt8 gj = (palette[j] >> 8) & 0xff; - uInt8 bj = palette[j] & 0xff; - - *ptr++ = tiaSurface.getPhosphor(ri, rj); - *ptr++ = tiaSurface.getPhosphor(gi, gj); - *ptr++ = tiaSurface.getPhosphor(bi, bj); - } - } -#endif - // Set palette for normal fill - for(int i = 0; i < 256; ++i) - { - *ptr++ = (palette[i] >> 16) & 0xff; - *ptr++ = (palette[i] >> 8) & 0xff; - *ptr++ = palette[i] & 0xff; - } - updateFilter(); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string NTSCFilter::setPreset(Preset preset) { @@ -98,7 +58,7 @@ string NTSCFilter::setPreset(Preset preset) default: return msg; } - updateFilter(); + myNTSC.initialize(mySetup, myTIAPalette); return msg; } diff --git a/src/common/tv_filters/NTSCFilter.hxx b/src/common/tv_filters/NTSCFilter.hxx index aa2472190..c1403521f 100644 --- a/src/common/tv_filters/NTSCFilter.hxx +++ b/src/common/tv_filters/NTSCFilter.hxx @@ -32,9 +32,7 @@ class Settings; and is derived from 'filter_ntsc.(h|c)'. Original code based on implementation from http://www.slack.net/~ant. - The class is basically a thin wrapper around atari_ntsc_xxx structs - and methods, so that the rest of the codebase isn't affected by - updated versions of Blargg code. + The class is basically a thin wrapper around the AtariNTSC class. */ class NTSCFilter { @@ -64,7 +62,18 @@ class NTSCFilter uses this as a baseline for calculating its own internal palette in YIQ format. */ - void setTIAPalette(const TIASurface& tiaSurface, const uInt32* palette); + inline void setTIAPalette(const uInt32* palette) { + uInt8* ptr = myTIAPalette; + + // Set palette for normal fill + for(uInt32 i = 0; i < AtariNTSC::palette_size; ++i) + { + *ptr++ = (palette[i] >> 16) & 0xff; + *ptr++ = (palette[i] >> 8) & 0xff; + *ptr++ = palette[i] & 0xff; + } + myNTSC.initializePalette(myTIAPalette); + } // The following are meant to be used strictly for toggling from the GUI string setPreset(Preset preset); @@ -72,13 +81,6 @@ class NTSCFilter // Get current preset info encoded as a string string getPreset() const; - // Reinitialises the NTSC filter (automatically called after settings - // have changed) - inline void updateFilter() - { - myNTSC.initialize(mySetup, myTIAPalette); - } - // Get adjustables for the given preset // Values will be scaled to 0 - 100 range, independent of how // they're actually stored internally @@ -106,8 +108,6 @@ class NTSCFilter // Perform Blargg filtering on input buffer, place results in // output buffer - // In the current implementation, the source pitch is always the - // same as the actual width inline void blit_single(uInt8* src_buf, uInt32 src_width, uInt32 src_height, uInt32* dest_buf, uInt32 dest_pitch) { diff --git a/src/emucore/Props.cxx b/src/emucore/Props.cxx index 52406aadd..b4fa7a1a4 100644 --- a/src/emucore/Props.cxx +++ b/src/emucore/Props.cxx @@ -63,10 +63,10 @@ void Properties::set(PropertyType key, const string& value) break; } - case Display_PPBlend: + case Display_PPBlend: // FIXME - handle global default { int blend = atoi(myProperties[key].c_str()); - if(blend < 0 || blend > 100) blend = 30; + if(blend < 1 || blend > 100) blend = 50; ostringstream buf; buf << blend; myProperties[key] = buf.str(); @@ -261,7 +261,14 @@ void Properties::print() const void Properties::setDefaults() { for(int i = 0; i < LastPropType; ++i) - myProperties[i] = ourDefaultProperties[i]; + { + if(i == Display_PPBlend) // special case, handle global default + { + myProperties[i] = "50"; // FIXME - for now, just use 50 + } + else + myProperties[i] = ourDefaultProperties[i]; + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -324,7 +331,7 @@ const char* Properties::ourDefaultProperties[LastPropType] = { "0", // Display.YStart "0", // Display.Height "NO", // Display.Phosphor - "30" // Display.PPBlend + "0" // Display.PPBlend }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/TIASurface.cxx b/src/emucore/TIASurface.cxx index 6c9efbde9..453d9cc9a 100644 --- a/src/emucore/TIASurface.cxx +++ b/src/emucore/TIASurface.cxx @@ -30,7 +30,7 @@ TIASurface::TIASurface(OSystem& system) : myOSystem(system), myFB(system.frameBuffer()), myTIA(nullptr), - myFilterType(kNormal), + myFilter(Filter::Normal), myUsePhosphor(false), myPhosphorPercent(0.60f), myScanlinesEnabled(false), @@ -53,6 +53,8 @@ TIASurface::TIASurface(OSystem& system) // Base TIA surface for use in taking snapshots in 1x mode myBaseTiaSurface = myFB.allocateSurface(kTIAW*2, kTIAH); + + memset(myRGBFramebuffer, 0, 160 * FrameManager::frameBufferHeight); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -97,7 +99,7 @@ void TIASurface::setPalette(const uInt32* tia_palette, const uInt32* rgb_palette // The NTSC filtering needs access to the raw RGB data, since it calculates // its own internal palette - myNTSCFilter.setTIAPalette(*this, rgb_palette); + myNTSCFilter.setTIAPalette(rgb_palette); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -124,7 +126,7 @@ const FBSurface& TIASurface::baseSurface(GUI::Rect& rect) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 TIASurface::pixel(uInt32 idx, uInt8 shift) const +uInt32 TIASurface::pixel(uInt32 idx, uInt8 shift) { uInt8 c = *(myTIA->frameBuffer() + idx) | shift; @@ -132,13 +134,13 @@ uInt32 TIASurface::pixel(uInt32 idx, uInt8 shift) const return myPalette[c]; else { - const uInt32 p = *(myTIA->rgbFramebuffer() + idx); + const uInt32 p = myRGBFramebuffer[idx]; // Mix current calculated frame with previous displayed frame const uInt32 retVal = getRGBPhosphor(myPalette[c], p, shift); // Store back into displayed frame buffer (for next frame) - *(myTIA->rgbFramebuffer() + idx) = retVal; + myRGBFramebuffer[idx] = retVal; return retVal; } @@ -225,7 +227,7 @@ void TIASurface::enablePhosphor(bool enable, int blend) { myUsePhosphor = enable; myPhosphorPercent = blend / 100.0; - myFilterType = FilterType(enable ? myFilterType | 0x01 : myFilterType & 0x10); + myFilter = Filter(enable ? uInt8(myFilter) | 0x01 : uInt8(myFilter) & 0x10); myTiaSurface->setDirty(); mySLineSurface->setDirty(); } @@ -238,15 +240,15 @@ inline uInt32 TIASurface::getRGBPhosphor(uInt32 c, uInt32 p, uInt8 shift) const myFB.getRGB(c, &rc, &gc, &bc); myFB.getRGB(p, &rp, &gp, &bp); - // mix current calculated frame with previous displayed frame + // Mix current calculated frame with previous displayed frame uInt8 rn = getPhosphor(rc, rp); uInt8 gn = getPhosphor(gc, gp); uInt8 bn = getPhosphor(bc, bp); if(shift) { - // convert RGB to grayscale - rn = gn = bn = (uInt8)(0.2126*rn + 0.7152*gn + 0.0722*bn); + // Convert RGB to grayscale + rn = gn = bn = uInt8(0.2126*rn + 0.7152*gn + 0.0722*bn); } return myFB.mapRGB(rn, gn, bn); @@ -255,7 +257,7 @@ inline uInt32 TIASurface::getRGBPhosphor(uInt32 c, uInt32 p, uInt8 shift) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TIASurface::enableNTSC(bool enable) { - myFilterType = FilterType(enable ? myFilterType | 0x10 : myFilterType & 0x01); + myFilter = Filter(enable ? uInt8(myFilter) | 0x10 : uInt8(myFilter) & 0x01); // Normal vs NTSC mode uses different source widths myTiaSurface->setSrcSize(enable ? AtariNTSC::outWidth(160) : 160, myTIA->height()); @@ -281,19 +283,19 @@ string TIASurface::effectsInfo() const const FBSurface::Attributes& attr = mySLineSurface->attributes(); ostringstream buf; - switch(myFilterType) + switch(myFilter) { - case kNormal: + case Filter::Normal: buf << "Disabled, normal mode"; break; - case kPhosphor: + case Filter::Phosphor: buf << "Disabled, phosphor mode"; break; - case kBlarggNormal: + case Filter::BlarggNormal: buf << myNTSCFilter.getPreset() << ", scanlines=" << attr.blendalpha << "/" << (attr.smoothing ? "inter" : "nointer"); break; - case kBlarggPhosphor: + case Filter::BlarggPhosphor: buf << myNTSCFilter.getPreset() << ", phosphor, scanlines=" << attr.blendalpha << "/" << (attr.smoothing ? "inter" : "nointer"); break; @@ -304,36 +306,36 @@ string TIASurface::effectsInfo() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TIASurface::render() { - // Copy the mediasource framebuffer to the RGB texture - // In hardware rendering mode, it's faster to just assume that the screen - // is dirty and always do an update + uInt32 width = myTIA->width(); + uInt32 height = myTIA->height(); - uInt8* tiaFrame = myTIA->frameBuffer(); - uInt32* rgbFrame = myTIA->rgbFramebuffer(); - uInt32 width = myTIA->width(); - uInt32 height = myTIA->height(); + uInt32 *out, outPitch; + myTiaSurface->basePtr(out, outPitch); - uInt32 *buffer, pitch; - myTiaSurface->basePtr(buffer, pitch); - - switch(myFilterType) + switch(myFilter) { - case kNormal: + case Filter::Normal: { + uInt8* in = myTIA->frameBuffer(); + uInt32 bufofsY = 0, screenofsY = 0, pos = 0; for(uInt32 y = 0; y < height; ++y) { pos = screenofsY; for(uInt32 x = 0; x < width; ++x) - buffer[pos++] = myPalette[tiaFrame[bufofsY + x]]; + out[pos++] = myPalette[in[bufofsY + x]]; bufofsY += width; - screenofsY += pitch; + screenofsY += outPitch; } break; } - case kPhosphor: + + case Filter::Phosphor: { + uInt8* tiaIn = myTIA->frameBuffer(); + uInt32* rgbIn = myRGBFramebuffer; + uInt32 bufofsY = 0, screenofsY = 0, pos = 0; for(uInt32 y = 0; y < height; ++y) { @@ -341,29 +343,30 @@ void TIASurface::render() for(uInt32 x = 0; x < width; ++x) { const uInt32 bufofs = bufofsY + x; - const uInt8 c = tiaFrame[bufofs]; - const uInt32 retVal = getRGBPhosphor(myPalette[c], rgbFrame[bufofs]); + const uInt8 c = tiaIn[bufofs]; + const uInt32 retVal = getRGBPhosphor(myPalette[c], rgbIn[bufofs]); // Store back into displayed frame buffer (for next frame) - rgbFrame[bufofs] = retVal; - buffer[pos++] = retVal; + rgbIn[bufofs] = retVal; + out[pos++] = retVal; } bufofsY += width; - screenofsY += pitch; + screenofsY += outPitch; } break; } - case kBlarggNormal: + + case Filter::BlarggNormal: { - myNTSCFilter.blit_single(tiaFrame, width, height, buffer, pitch << 2); + myNTSCFilter.blit_single(myTIA->frameBuffer(), width, height, + out, outPitch << 2); break; } - case kBlarggPhosphor: + + case Filter::BlarggPhosphor: { -#if 0 // FIXME - myNTSCFilter.blit_double(currentFrame, previousFrame, width, height, - buffer, pitch << 2); -#endif + myNTSCFilter.blit_single(myTIA->frameBuffer(), width, height, + out, outPitch << 2); break; } } diff --git a/src/emucore/TIASurface.hxx b/src/emucore/TIASurface.hxx index 41cf1998c..d00a276df 100644 --- a/src/emucore/TIASurface.hxx +++ b/src/emucore/TIASurface.hxx @@ -25,6 +25,7 @@ class FrameBuffer; class FBSurface; class VideoMode; +#include "FrameManager.hxx" #include "Rect.hxx" #include "NTSCFilter.hxx" #include "bspf.hxx" @@ -73,7 +74,7 @@ class TIASurface Get the TIA pixel associated with the given TIA buffer index, shifting by the given offset (for greyscale values). */ - uInt32 pixel(uInt32 idx, uInt8 shift = 0) const; + uInt32 pixel(uInt32 idx, uInt8 shift = 0); /** Get the NTSCFilter object associated with the framebuffer @@ -118,7 +119,7 @@ class TIASurface @return Averaged value of the two colors */ - uInt8 getPhosphor(uInt8 c1, uInt8 c2) const { + inline uInt8 getPhosphor(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) @@ -139,7 +140,7 @@ class TIASurface Enable/disable/query NTSC filtering effects. */ void enableNTSC(bool enable); - bool ntscEnabled() const { return myFilterType & 0x10; } + bool ntscEnabled() const { return uInt8(myFilter) & 0x10; } string effectsInfo() const; /** @@ -156,13 +157,13 @@ class TIASurface // Enumeration created such that phosphor off/on is in LSB, // and Blargg off/on is in MSB - enum FilterType { - kNormal = 0x00, - kPhosphor = 0x01, - kBlarggNormal = 0x10, - kBlarggPhosphor = 0x11 + enum class Filter: uInt8 { + Normal = 0x00, + Phosphor = 0x01, + BlarggNormal = 0x10, + BlarggPhosphor = 0x11 }; - FilterType myFilterType; + Filter myFilter; enum TIAConstants { kTIAW = 160, @@ -173,11 +174,17 @@ class TIASurface // NTSC object to use in TIA rendering mode NTSCFilter myNTSCFilter; - // Use phosphor effect (aka no flicker on 30Hz screens) + ///////////////////////////////////////////////////////////// + // Phosphor mode items (aka reduced flicker on 30Hz screens) + // RGB frame buffer + uInt32 myRGBFramebuffer[160 * FrameManager::frameBufferHeight]; + + // Use phosphor effect bool myUsePhosphor; // Amount to blend when using phosphor effect float myPhosphorPercent; + ///////////////////////////////////////////////////////////// // Use scanlines in TIA rendering mode bool myScanlinesEnabled; diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index b644fc093..600f78327 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -88,9 +88,6 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings) } ); - myFramebuffer = make_ptr(160 * FrameManager::frameBufferHeight); - myRGBFramebuffer = make_ptr(160 * FrameManager::frameBufferHeight); - myTIAPinsDriven = mySettings.getBool("tiadriven"); myBackground.setTIA(this); @@ -155,8 +152,7 @@ void TIA::reset() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TIA::frameReset() { - memset(myFramebuffer.get(), 0, 160 * FrameManager::frameBufferHeight); - memset(myRGBFramebuffer.get(), 0, 160 * FrameManager::frameBufferHeight); + memset(myFramebuffer, 0, 160 * FrameManager::frameBufferHeight); myAutoFrameEnabled = mySettings.getInt("framerate") <= 0; enableColorLoss(mySettings.getBool("colorloss")); } @@ -712,7 +708,7 @@ bool TIA::saveDisplay(Serializer& out) const { try { - out.putByteArray(myFramebuffer.get(), 160*FrameManager::frameBufferHeight); + out.putByteArray(myFramebuffer, 160*FrameManager::frameBufferHeight); } catch(...) { @@ -729,7 +725,7 @@ bool TIA::loadDisplay(Serializer& in) try { // Reset frame buffer pointer and data - in.getByteArray(myFramebuffer.get(), 160*FrameManager::frameBufferHeight); + in.getByteArray(myFramebuffer, 160*FrameManager::frameBufferHeight); } catch(...) { @@ -1027,12 +1023,12 @@ void TIA::onFrameComplete() mySystem->resetCycles(); if (myXAtRenderingStart > 0) - memset(myFramebuffer.get(), 0, myXAtRenderingStart); + memset(myFramebuffer, 0, myXAtRenderingStart); // Blank out any extra lines not drawn this frame const uInt32 missingScanlines = myFrameManager.missingScanlines(); if (missingScanlines > 0) - memset(myFramebuffer.get() + 160 * myFrameManager.getY(), 0, missingScanlines * 160); + memset(myFramebuffer + 160 * myFrameManager.getY(), 0, missingScanlines * 160); // Recalculate framerate, attempting to auto-correct for scanline 'jumps' if(myAutoFrameEnabled) @@ -1143,7 +1139,7 @@ void TIA::applyRsync() myHctrDelta = 225 - myHctr; if (myFrameManager.isRendering()) - memset(myFramebuffer.get() + myFrameManager.getY() * 160 + x, 0, 160 - x); + memset(myFramebuffer + myFrameManager.getY() * 160 + x, 0, 160 - x); myHctr = 225; } @@ -1176,7 +1172,7 @@ void TIA::cloneLastLine() if (!myFrameManager.isRendering() || y == 0) return; - uInt8* buffer = myFramebuffer.get(); + uInt8* buffer = myFramebuffer; memcpy(buffer + y * 160, buffer + (y-1) * 160, 160); } @@ -1243,7 +1239,7 @@ void TIA::renderPixel(uInt32 x, uInt32 y) break; } - myFramebuffer.get()[y * 160 + x] = myFrameManager.vblank() ? 0 : color; + myFramebuffer[y * 160 + x] = myFrameManager.vblank() ? 0 : color; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1269,8 +1265,7 @@ void TIA::flushLineCache() void TIA::clearHmoveComb() { if (myFrameManager.isRendering() && myHstate == HState::blank) - memset(myFramebuffer.get() + myFrameManager.getY() * 160, - myColorHBlank, 8); + memset(myFramebuffer + myFrameManager.getY() * 160, myColorHBlank, 8); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx index 0280f6ca9..7c7f13152 100644 --- a/src/emucore/tia/TIA.hxx +++ b/src/emucore/tia/TIA.hxx @@ -157,10 +157,9 @@ class TIA : public Device void update(); /** - Returns a pointer to the internal frame buffer(s). + Returns a pointer to the internal frame buffer. */ - uInt8* frameBuffer() const { return myFramebuffer.get(); } - uInt32* rgbFramebuffer() const { return myRGBFramebuffer.get(); } + uInt8* frameBuffer() const { return (uInt8*)(myFramebuffer); } /** Answers dimensional info about the framebuffer. @@ -468,11 +467,8 @@ class TIA : public Device LatchedInput myInput0; LatchedInput myInput1; - // Pointer to the internal frame buffer - BytePtr myFramebuffer; - - // Pointer to the RGB frame buffer (used for phosphor) - std::unique_ptr myRGBFramebuffer; + // Pointer to the internal color-index-based frame buffer + uInt8 myFramebuffer[160 * FrameManager::frameBufferHeight]; bool myTIAPinsDriven; diff --git a/src/tools/PropSet.pm b/src/tools/PropSet.pm index 51a0fdefe..198cde297 100755 --- a/src/tools/PropSet.pm +++ b/src/tools/PropSet.pm @@ -70,7 +70,7 @@ my @prop_defaults = ( "0", "0", "NO", - "30" + "0" ); # Load and parse a properties file into an hash table of property