From 4750c64a1766302ce8a7322f0ef389936a6566da Mon Sep 17 00:00:00 2001 From: stephena Date: Sat, 26 May 2012 22:18:13 +0000 Subject: [PATCH] Phosphor mode now works with Blargg TV effects! It takes an extra 2-3 MB RAM to do so, which I agonized over for about a week, but I feel it's a fairly good tradeoff for the features we get. Eventually, I may come up with a more accurate phosphor mode which eliminates this approach entirely. Reverted OpenGL framebuffer to 32-bit colour mode. We're using Blargg effects, so we may as well get the full fidelity out of it. Besides, testing has shown that there's not much speed difference between 16 and 32 bit modes, making me think that 16-bit is probably be swizzled to 32-bit anyway. Bumped release date to June 1, version to rc1. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2501 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- Changes.txt | 2 +- Readme.txt | 2 +- debian/changelog | 2 +- docs/index.html | 2 +- src/common/FBSurfaceGL.cxx | 24 +++---- src/common/FBSurfaceTIA.cxx | 36 +++++----- src/common/FrameBufferGL.cxx | 15 ++-- src/common/FrameBufferGL.hxx | 11 +-- src/common/Version.hxx | 2 +- src/common/tv_filters/NTSCFilter.cxx | 32 ++++++++- src/common/tv_filters/NTSCFilter.hxx | 35 ++++++--- src/common/tv_filters/atari_ntsc.c | 104 +++++++++++++++++++++------ src/common/tv_filters/atari_ntsc.h | 24 +++---- src/emucore/EventHandler.cxx | 4 +- src/emucore/FrameBuffer.hxx | 20 +++--- src/unix/stella.SlackBuild | 2 +- src/unix/stella.spec | 5 +- 17 files changed, 219 insertions(+), 103 deletions(-) diff --git a/Changes.txt b/Changes.txt index 35cc23018..d418b91a1 100644 --- a/Changes.txt +++ b/Changes.txt @@ -12,7 +12,7 @@ Release History =========================================================================== -3.6.1 to 3.7: (May 25, 2012) +3.6.1 to 3.7: (June 1, 2012) * Added Blargg TV effects, with presets for Composite, S-video, RGB, and badly adjusted TV, and well as a custom mode with full diff --git a/Readme.txt b/Readme.txt index 589f9a8eb..e7ca819e3 100644 --- a/Readme.txt +++ b/Readme.txt @@ -9,4 +9,4 @@ the Stella Website at: Enjoy, The Stella Team -May 25, 2012 +June 1, 2012 diff --git a/debian/changelog b/debian/changelog index 74e2d0f41..c5062a64f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,7 +2,7 @@ stella (3.7-1) stable; urgency=high * Version 3.7 release - -- Stephen Anthony Fri, 25 May 2012 18:38:25 +0200 + -- Stephen Anthony Fri, 1 Jun 2012 18:38:25 +0200 stella (3.6.1-1) stable; urgency=high diff --git a/docs/index.html b/docs/index.html index 5b61a02a6..77413ca9a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -54,7 +54,7 @@


-
February 1999 - May 2012
+
February 1999 - June 2012
The Stella Team
Stella Homepage
diff --git a/src/common/FBSurfaceGL.cxx b/src/common/FBSurfaceGL.cxx index b9a46faa0..2bed848e1 100644 --- a/src/common/FBSurfaceGL.cxx +++ b/src/common/FBSurfaceGL.cxx @@ -66,18 +66,18 @@ FBSurfaceGL::~FBSurfaceGL() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FBSurfaceGL::hLine(uInt32 x, uInt32 y, uInt32 x2, uInt32 color) { - uInt16* buffer = (uInt16*) myTexture->pixels + y * myPitch + x; + uInt32* buffer = (uInt32*) myTexture->pixels + y * myPitch + x; while(x++ <= x2) - *buffer++ = (uInt16) myFB.myDefPalette[color]; + *buffer++ = (uInt32) myFB.myDefPalette[color]; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FBSurfaceGL::vLine(uInt32 x, uInt32 y, uInt32 y2, uInt32 color) { - uInt16* buffer = (uInt16*) myTexture->pixels + y * myPitch + x; + uInt32* buffer = (uInt32*) myTexture->pixels + y * myPitch + x; while(y++ <= y2) { - *buffer = (uInt16) myFB.myDefPalette[color]; + *buffer = (uInt32) myFB.myDefPalette[color]; buffer += myPitch; } } @@ -126,7 +126,7 @@ void FBSurfaceGL::drawChar(const GUI::Font& font, uInt8 chr, } const uInt16* tmp = desc.bits + (desc.offset ? desc.offset[chr] : (chr * desc.fbbh)); - uInt16* buffer = (uInt16*) myTexture->pixels + + uInt32* buffer = (uInt32*) myTexture->pixels + (ty + desc.ascent - bby - bbh) * myPitch + tx + bbx; @@ -137,7 +137,7 @@ void FBSurfaceGL::drawChar(const GUI::Font& font, uInt8 chr, for(int x = 0; x < bbw; x++, mask >>= 1) if(ptr & mask) - buffer[x] = (uInt16) myFB.myDefPalette[color]; + buffer[x] = (uInt32) myFB.myDefPalette[color]; buffer += myPitch; } @@ -147,14 +147,14 @@ void FBSurfaceGL::drawChar(const GUI::Font& font, uInt8 chr, void FBSurfaceGL::drawBitmap(uInt32* bitmap, uInt32 tx, uInt32 ty, uInt32 color, uInt32 h) { - uInt16* buffer = (uInt16*) myTexture->pixels + ty * myPitch + tx; + uInt32* buffer = (uInt32*) myTexture->pixels + ty * myPitch + tx; for(uInt32 y = 0; y < h; ++y) { uInt32 mask = 0xF0000000; for(uInt32 x = 0; x < 8; ++x, mask >>= 4) if(bitmap[y] & mask) - buffer[x] = (uInt16) myFB.myDefPalette[color]; + buffer[x] = (uInt32) myFB.myDefPalette[color]; buffer += myPitch; } @@ -163,10 +163,10 @@ void FBSurfaceGL::drawBitmap(uInt32* bitmap, uInt32 tx, uInt32 ty, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FBSurfaceGL::drawPixels(uInt32* data, uInt32 tx, uInt32 ty, uInt32 numpixels) { - uInt16* buffer = (uInt16*) myTexture->pixels + ty * myPitch + tx; + uInt32* buffer = (uInt32*) myTexture->pixels + ty * myPitch + tx; for(uInt32 i = 0; i < numpixels; ++i) - *buffer++ = (uInt16) data[i]; + *buffer++ = (uInt32) data[i]; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -259,7 +259,7 @@ void FBSurfaceGL::update() myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1); myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch); myGL.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myImageW, myImageH, - GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, myTexture->pixels); myGL.EnableClientState(GL_VERTEX_ARRAY); @@ -318,7 +318,7 @@ void FBSurfaceGL::reload() myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1); myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch); myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexWidth, myTexHeight, 0, - GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, myTexture->pixels); // Cache vertex and texture coordinates using vertex buffer object diff --git a/src/common/FBSurfaceTIA.cxx b/src/common/FBSurfaceTIA.cxx index 1a814ae3b..5b8d447ee 100644 --- a/src/common/FBSurfaceTIA.cxx +++ b/src/common/FBSurfaceTIA.cxx @@ -89,13 +89,13 @@ void FBSurfaceTIA::update() uInt8* previousFrame = myTIA->previousFrameBuffer(); uInt32 width = myTIA->width(); uInt32 height = myTIA->height(); - uInt16* buffer = (uInt16*) myTexture->pixels; + uInt32* buffer = (uInt32*) myTexture->pixels; // TODO - Eventually 'phosphor' won't be a separate mode, and will become // a post-processing filter by blending several frames. switch(myFB.myFilterType) { - case FrameBufferGL::kNone: + case FrameBufferGL::kNormal: { uInt32 bufofsY = 0; uInt32 screenofsY = 0; @@ -103,14 +103,13 @@ void FBSurfaceTIA::update() { uInt32 pos = screenofsY; for(uInt32 x = 0; x < width; ++x) - buffer[pos++] = (uInt16) myFB.myDefPalette[currentFrame[bufofsY + x]]; + buffer[pos++] = (uInt32) myFB.myDefPalette[currentFrame[bufofsY + x]]; bufofsY += width; screenofsY += myPitch; } break; } - case FrameBufferGL::kPhosphor: { uInt32 bufofsY = 0; @@ -121,7 +120,7 @@ void FBSurfaceTIA::update() for(uInt32 x = 0; x < width; ++x) { const uInt32 bufofs = bufofsY + x; - buffer[pos++] = (uInt16) + buffer[pos++] = (uInt32) myFB.myAvgPalette[currentFrame[bufofs]][previousFrame[bufofs]]; } bufofsY += width; @@ -129,10 +128,16 @@ void FBSurfaceTIA::update() } break; } - - case FrameBufferGL::kBlarggNTSC: + case FrameBufferGL::kBlarggNormal: { - myFB.myNTSCFilter.blit(currentFrame, width, height, buffer, myTexture->pitch); + myFB.myNTSCFilter.blit_single(currentFrame, width, height, + buffer, myTexture->pitch); + break; + } + case FrameBufferGL::kBlarggPhosphor: + { + myFB.myNTSCFilter.blit_double(currentFrame, previousFrame, width, height, + buffer, myTexture->pitch); break; } } @@ -146,7 +151,7 @@ void FBSurfaceTIA::update() myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1); myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch); myGL.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myBaseW, myBaseH, - GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, myTexture->pixels); if(myFB.myVBOAvailable) @@ -231,7 +236,7 @@ void FBSurfaceTIA::reload() myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1); myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, myPitch); myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexWidth, myTexHeight, 0, - GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, myTexture->pixels); // Scanline texture (@ index 1) @@ -241,11 +246,11 @@ void FBSurfaceTIA::reload() myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - static uInt16 const scanline[4] = { 0x0000, 0x0000, 0x8000, 0x0000 }; + static uInt32 const scanline[2] = { 0x00000000, 0xff000000 }; myGL.PixelStorei(GL_UNPACK_ALIGNMENT, 1); - myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, 2); + myGL.PixelStorei(GL_UNPACK_ROW_LENGTH, 1); myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0, - GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, scanline); // Cache vertex and texture coordinates using vertex buffer object @@ -302,8 +307,7 @@ void FBSurfaceTIA::updateCoords() { // Normal TIA rendering and TV effects use different widths // We use the same buffer, and only pick the width we need - myBaseW = myFB.myFilterType == FrameBufferGL::kBlarggNTSC ? - ATARI_NTSC_OUT_WIDTH(160) : 160; + myBaseW = myFB.ntscEnabled() ? ATARI_NTSC_OUT_WIDTH(160) : 160; myTexCoordW = (GLfloat) myBaseW / myTexWidth; myTexCoordH = (GLfloat) myBaseH / myTexHeight; @@ -379,7 +383,7 @@ void FBSurfaceTIA::updateCoords() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FBSurfaceTIA::setTIAPalette(const uInt32* palette) { - myFB.myNTSCFilter.setTIAPalette(palette); + myFB.myNTSCFilter.setTIAPalette(myFB, palette); } #endif diff --git a/src/common/FrameBufferGL.cxx b/src/common/FrameBufferGL.cxx index fb46ee99f..7b89700e6 100644 --- a/src/common/FrameBufferGL.cxx +++ b/src/common/FrameBufferGL.cxx @@ -40,7 +40,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FrameBufferGL::FrameBufferGL(OSystem* osystem) : FrameBuffer(osystem), - myFilterType(kNone), + myFilterType(kNormal), myTiaSurface(NULL), myDirtyFlag(true) { @@ -48,8 +48,9 @@ FrameBufferGL::FrameBufferGL(OSystem* osystem) // It's done this way (vs directly accessing a FBSurfaceGL object) // since the structure may be needed before any FBSurface's have // been created - SDL_Surface* s = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1,16, - 0x00007c00, 0x000003e0, 0x0000001f, 0x00000000); + // Note: alpha disabled for now, since it's not used + SDL_Surface* s = SDL_CreateRGBSurface(SDL_SWSURFACE, 1, 1, 32, + 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000); myPixelFormat = *(s->format); SDL_FreeSurface(s); @@ -313,7 +314,7 @@ bool FrameBufferGL::setVidMode(VideoMode& mode) myTiaSurface->updateCoords(baseHeight, mode.image_x, mode.image_y, mode.image_w, mode.image_h); - myTiaSurface->enableScanlines(myFilterType == kBlarggNTSC); + myTiaSurface->enableScanlines(ntscEnabled()); myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv_scanlines")); myTiaSurface->setTexInterpolation(myOSystem->settings().getBool("gl_inter")); myTiaSurface->setScanInterpolation(myOSystem->settings().getBool("tv_scaninter")); @@ -358,7 +359,7 @@ void FrameBufferGL::enablePhosphor(bool enable, int blend) { myUsePhosphor = enable; myPhosphorBlend = blend; - myFilterType = enable ? kPhosphor : kNone; + myFilterType = FilterType(enable ? myFilterType | 0x01 : myFilterType & 0x10); myRedrawEntireFrame = true; } } @@ -368,10 +369,10 @@ void FrameBufferGL::enableNTSC(bool enable) { if(myTiaSurface) { - myFilterType = enable ? kBlarggNTSC : myUsePhosphor ? kPhosphor : kNone; + myFilterType = FilterType(enable ? myFilterType | 0x10 : myFilterType & 0x01); myTiaSurface->updateCoords(); - myTiaSurface->enableScanlines(myFilterType == kBlarggNTSC); + myTiaSurface->enableScanlines(ntscEnabled()); myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv_scanlines")); myTiaSurface->setTexInterpolation(myOSystem->settings().getBool("gl_inter")); myTiaSurface->setScanInterpolation(myOSystem->settings().getBool("tv_scaninter")); diff --git a/src/common/FrameBufferGL.hxx b/src/common/FrameBufferGL.hxx index 1aaab2bca..9a7e0391d 100644 --- a/src/common/FrameBufferGL.hxx +++ b/src/common/FrameBufferGL.hxx @@ -77,7 +77,7 @@ class FrameBufferGL : public FrameBuffer Enable/disable NTSC filtering effects. */ void enableNTSC(bool enable); - bool ntscEnabled() const { return myFilterType == kBlarggNTSC; } + bool ntscEnabled() const { return myFilterType & 0x10; } /** Set up the TIA/emulation palette for a screen of any depth > 8. @@ -193,10 +193,13 @@ class FrameBufferGL : public FrameBuffer }; bool loadFuncs(GLFunctionality functionality); + // Enumeration created such that phosphor off/on is in LSB, + // and Blargg off/on is in MSB enum FilterType { - kNone, - kPhosphor, - kBlarggNTSC + kNormal = 0x00, + kPhosphor = 0x01, + kBlarggNormal = 0x10, + kBlarggPhosphor = 0x11 }; FilterType myFilterType; diff --git a/src/common/Version.hxx b/src/common/Version.hxx index 469320939..daa460302 100644 --- a/src/common/Version.hxx +++ b/src/common/Version.hxx @@ -22,7 +22,7 @@ #include -#define STELLA_VERSION "3.7_beta4" +#define STELLA_VERSION "3.7_rc1" #define STELLA_BUILD atoi("$Rev$" + 6) #endif diff --git a/src/common/tv_filters/NTSCFilter.cxx b/src/common/tv_filters/NTSCFilter.cxx index 2f2c292c4..a7df91003 100644 --- a/src/common/tv_filters/NTSCFilter.cxx +++ b/src/common/tv_filters/NTSCFilter.cxx @@ -17,6 +17,9 @@ // $Id$ //============================================================================ +#include "FrameBuffer.hxx" +#include "Settings.hxx" + #include "NTSCFilter.hxx" #define SCALE_FROM_100(x) ((x/50.0)-1.0) @@ -36,10 +39,35 @@ NTSCFilter::~NTSCFilter() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void NTSCFilter::setTIAPalette(const uInt32* palette) +void NTSCFilter::setTIAPalette(const FrameBuffer& fb, 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; - for(int i = 0; i < 256; i++) + + // 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++ = fb.getPhosphor(ri, rj); + *ptr++ = fb.getPhosphor(gi, gj); + *ptr++ = fb.getPhosphor(bi, bj); + } + } + // Set palette for normal fill + for(int i = 0; i < 256; i+=2) { *ptr++ = (palette[i] >> 16) & 0xff; *ptr++ = (palette[i] >> 8) & 0xff; diff --git a/src/common/tv_filters/NTSCFilter.hxx b/src/common/tv_filters/NTSCFilter.hxx index 5c5dd97b4..8dfbf8a42 100644 --- a/src/common/tv_filters/NTSCFilter.hxx +++ b/src/common/tv_filters/NTSCFilter.hxx @@ -20,9 +20,10 @@ #ifndef NTSC_FILTER_HXX #define NTSC_FILTER_HXX +class FrameBuffer; +class Settings; + #include "bspf.hxx" -#include "Array.hxx" -#include "Settings.hxx" #include "atari_ntsc.h" /** @@ -63,7 +64,7 @@ class NTSCFilter uses this as a baseline for calculating its own internal palette in YIQ format. */ - void setTIAPalette(const uInt32* palette); + void setTIAPalette(const FrameBuffer& fb, const uInt32* palette); // The following are meant to be used strictly for toggling from the GUI string setPreset(Preset preset); @@ -104,11 +105,18 @@ class NTSCFilter // output buffer // In the current implementation, the source pitch is always the // same as the actual width - inline void blit(uInt8* src_buf, int src_width, int src_height, - uInt16* dest_buf, long dest_pitch) + inline void blit_single(uInt8* src_buf, int src_width, int src_height, + uInt32* dest_buf, long dest_pitch) { - atari_ntsc_blit(&myFilter, src_buf, src_width, src_width, src_height, - dest_buf, dest_pitch); + atari_ntsc_blit_single(&myFilter, src_buf, src_width, src_width, src_height, + dest_buf, dest_pitch); + } + inline void blit_double(uInt8* src_buf, uInt8* src_back_buf, + int src_width, int src_height, + uInt32* dest_buf, long dest_pitch) + { + atari_ntsc_blit_double(&myFilter, src_buf, src_back_buf, src_width, src_width, + src_height, dest_buf, dest_pitch); } private: @@ -131,8 +139,17 @@ class NTSCFilter // Current preset in use Preset myPreset; - // 128 colours by 3 components per colour - uInt8 myTIAPalette[256 * 3]; + // The base 2600 palette contains 128 colours + // However, 'phosphor' mode needs a 128x128 matrix to simulate + // low-flicker output, so we need 128x128 + 128, or 129x128 + // Note that this is a huge hack, which hopefully will go + // away once the phosphor effect can be more properly emulated + // Memory layout is as follows: + // + // 128x128 in first bytes of array + // 128 in last bytes of array + // Each colour is represented by 3 bytes, in R,G,B order + uInt8 myTIAPalette[atari_ntsc_palette_size * 3]; struct AdjustableTag { const char* type; diff --git a/src/common/tv_filters/atari_ntsc.c b/src/common/tv_filters/atari_ntsc.c index 78a17b896..97aae30c2 100644 --- a/src/common/tv_filters/atari_ntsc.c +++ b/src/common/tv_filters/atari_ntsc.c @@ -99,15 +99,18 @@ void atari_ntsc_init( atari_ntsc_t* ntsc, atari_ntsc_setup_t const* setup, } } -void atari_ntsc_blit( atari_ntsc_t const* ntsc, atari_ntsc_in_t const* atari_in, +void atari_ntsc_blit_single( atari_ntsc_t const* ntsc, + atari_ntsc_in_t const* atari_in, long in_row_width, int in_width, int in_height, void* rgb_out, long out_pitch ) { + #define TO_SINGLE(pixel) ((1<<14)+(pixel>>1)) + int const chunk_count = (in_width - 1) / atari_ntsc_in_chunk; while ( in_height-- ) { atari_ntsc_in_t const* line_in = atari_in; - ATARI_NTSC_BEGIN_ROW( ntsc, atari_ntsc_black, line_in[0] ); + ATARI_NTSC_BEGIN_ROW( ntsc, TO_SINGLE(atari_ntsc_black), TO_SINGLE(line_in[0]) ); atari_ntsc_out_t* restrict line_out = (atari_ntsc_out_t*) rgb_out; int n; ++line_in; @@ -115,34 +118,95 @@ void atari_ntsc_blit( atari_ntsc_t const* ntsc, atari_ntsc_in_t const* atari_in, for ( n = chunk_count; n; --n ) { /* order of input and output pixels must not be altered */ - ATARI_NTSC_COLOR_IN( 0, ntsc, line_in[0] ); - ATARI_NTSC_RGB_OUT_1555( 0, line_out[0] ); - ATARI_NTSC_RGB_OUT_1555( 1, line_out[1] ); - ATARI_NTSC_RGB_OUT_1555( 2, line_out[2] ); - ATARI_NTSC_RGB_OUT_1555( 3, line_out[3] ); + ATARI_NTSC_COLOR_IN( 0, ntsc, TO_SINGLE(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, ntsc, line_in[1] ); - ATARI_NTSC_RGB_OUT_1555( 4, line_out[4] ); - ATARI_NTSC_RGB_OUT_1555( 5, line_out[5] ); - ATARI_NTSC_RGB_OUT_1555( 6, line_out[6] ); + ATARI_NTSC_COLOR_IN( 1, ntsc, TO_SINGLE(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] ); line_in += 2; line_out += 7; } /* finish final pixels */ - ATARI_NTSC_COLOR_IN( 0, ntsc, atari_ntsc_black ); - ATARI_NTSC_RGB_OUT_1555( 0, line_out[0] ); - ATARI_NTSC_RGB_OUT_1555( 1, line_out[1] ); - ATARI_NTSC_RGB_OUT_1555( 2, line_out[2] ); - ATARI_NTSC_RGB_OUT_1555( 3, line_out[3] ); + ATARI_NTSC_COLOR_IN( 0, ntsc, TO_SINGLE(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, atari_ntsc_black ); - ATARI_NTSC_RGB_OUT_1555( 4, line_out[4] ); - ATARI_NTSC_RGB_OUT_1555( 5, line_out[5] ); - ATARI_NTSC_RGB_OUT_1555( 6, line_out[6] ); + ATARI_NTSC_COLOR_IN( 1, ntsc, TO_SINGLE(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_in += in_row_width; rgb_out = (char*) rgb_out + out_pitch; } } + +void atari_ntsc_blit_double( atari_ntsc_t const* ntsc, + atari_ntsc_in_t const* atari_in1, atari_ntsc_in_t const* atari_in2, + long in_row_width, int in_width, int in_height, + void* rgb_out, long out_pitch ) +{ + #define TO_DOUBLE(pixel1, pixel2) (((pixel1>>1)<<7)+(pixel2>>1)) + + int 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]) ); + atari_ntsc_out_t* restrict line_out = (atari_ntsc_out_t*) rgb_out; + int n; + ++line_in1; + ++line_in2; + + for ( 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_row_width; + atari_in2 += in_row_width; + rgb_out = (char*) rgb_out + out_pitch; + } +} diff --git a/src/common/tv_filters/atari_ntsc.h b/src/common/tv_filters/atari_ntsc.h index 5edc860f8..d09f34749 100644 --- a/src/common/tv_filters/atari_ntsc.h +++ b/src/common/tv_filters/atari_ntsc.h @@ -23,7 +23,7 @@ #define ATARI_NTSC_H typedef unsigned char atari_ntsc_in_t; -typedef unsigned short atari_ntsc_out_t; +typedef unsigned int atari_ntsc_out_t; #ifdef __cplusplus extern "C" { @@ -55,7 +55,7 @@ extern atari_ntsc_setup_t const atari_ntsc_svideo; /* color bleeding only */ extern atari_ntsc_setup_t const atari_ntsc_rgb; /* crisp image */ extern atari_ntsc_setup_t const atari_ntsc_bad; /* badly adjusted TV */ -enum { atari_ntsc_palette_size = 256 }; +enum { atari_ntsc_palette_size = 129 * 128 }; /* Initializes and adjusts parameters. Can be called multiple times on the same atari_ntsc_t object. Can pass NULL for either parameter. */ @@ -66,7 +66,12 @@ void atari_ntsc_init( atari_ntsc_t* ntsc, atari_ntsc_setup_t const* setup, /* Filters one or more rows of pixels. Input pixels are 8-bit Atari palette colors. In_row_width is the number of pixels to get to the next input row. Out_pitch is the number of *bytes* to get to the next output row. */ -void atari_ntsc_blit( atari_ntsc_t const* ntsc, atari_ntsc_in_t const* atari_in, +void atari_ntsc_blit_single( atari_ntsc_t const* ntsc, + atari_ntsc_in_t const* atari_in, + long in_row_width, int in_width, int in_height, + void* rgb_out, long out_pitch ); +void atari_ntsc_blit_double( atari_ntsc_t const* ntsc, + atari_ntsc_in_t const* atari_in1, atari_ntsc_in_t const* atari_in2, long in_row_width, int in_width, int in_height, void* rgb_out, long out_pitch ); @@ -99,23 +104,16 @@ enum { atari_ntsc_black = 0 }; /* palette index for black */ #define ATARI_NTSC_COLOR_IN( in_index, ntsc, color_in ) \ ATARI_NTSC_COLOR_IN_( in_index, color_in, ATARI_NTSC_ENTRY_, ntsc ) -/* Generates output in the specified 16-bit format (x = junk bits). - 1555: xRRRRRGG GGGBBBBB (1-5-5-5 16-bit RGB) +/* Generates output in the specified 32-bit format (x = junk bits). native: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format) + 8888: 00000000 RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8-8 32-bit ARGB) */ -#define ATARI_NTSC_RGB_OUT_1555( index, rgb_out ) {\ - atari_ntsc_rgb_t raw_ =\ - kernel0 [index ] + kernel1 [(index+10)%7+14] +\ - kernelx0 [(index+7)%14] + kernelx1 [(index+ 3)%7+14+7];\ - ATARI_NTSC_CLAMP_( raw_, 0 );\ - rgb_out = (raw_>>(14)& 0x7C00)|(raw_>>(9)&0x03E0)|(raw_>>(4)&0x001F);\ -} #define ATARI_NTSC_RGB_OUT_8888( index, rgb_out ) {\ atari_ntsc_rgb_t raw_ =\ kernel0 [index ] + kernel1 [(index+10)%7+14] +\ kernelx0 [(index+7)%14] + kernelx1 [(index+ 3)%7+14+7];\ 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);\ } /* private */ diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index 68fa9f62f..ba72c2a3d 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -495,9 +495,7 @@ void EventHandler::poll(uInt64 time) break; case KBDK_p: // Alt-p toggles phosphor effect - // FIXME - Currently, phosphor mode cannot be enabled with NTSC filtering - if(!myOSystem->frameBuffer().ntscEnabled()) - myOSystem->console().togglePhosphor(); + myOSystem->console().togglePhosphor(); break; case KBDK_l: diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx index 2509229af..a3c610ef2 100644 --- a/src/emucore/FrameBuffer.hxx +++ b/src/emucore/FrameBuffer.hxx @@ -305,6 +305,16 @@ class FrameBuffer */ void toggleScanlineInterpolation(); + /** + 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 + */ + uInt8 getPhosphor(uInt8 c1, uInt8 c2) const; + ////////////////////////////////////////////////////////////////////// // The following methods are system-specific and *may* be implemented // in derived classes. @@ -530,16 +540,6 @@ class FrameBuffer */ void drawMessage(); - /** - 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 - */ - uInt8 getPhosphor(uInt8 c1, uInt8 c2) const; - /** Calculate the maximum level by which the base window can be zoomed and still fit in the given screen dimensions. diff --git a/src/unix/stella.SlackBuild b/src/unix/stella.SlackBuild index cdcf36ebe..8cd4ed422 100644 --- a/src/unix/stella.SlackBuild +++ b/src/unix/stella.SlackBuild @@ -51,7 +51,7 @@ stella: support, and an integrated debugger for VCS game developers (with DASM stella: symbol file support). stella: stella: Homepage: http://stella.sourceforge.net/ -stella: Author: Bradford W. Mott and the Stella Team +stella: Author: Bradford W. Mott, Stephen Anthony and the Stella Team stella: stella: EOF diff --git a/src/unix/stella.spec b/src/unix/stella.spec index 9099c5f04..f518cbb46 100644 --- a/src/unix/stella.spec +++ b/src/unix/stella.spec @@ -108,9 +108,12 @@ rm -rf $RPM_BUILD_DIR/%{name}-%{version} %_datadir/icons/large/%{name}.png %changelog -* Fri May 25 2012 Stephen Anthony 3.7-1 +* Fri Jun 1 2012 Stephen Anthony 3.7-1 - Version 3.7 release +* Fri Mar 30 2012 Stephen Anthony 3.6.1-1 +- Version 3.6.1 release + * Fri Mar 16 2012 Stephen Anthony 3.6-1 - Version 3.6 release